<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:admin="http://webns.net/mvcb/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
<channel>
    <title>Nico Steiner - Frontend-Entwicklung und -Architektur</title>
    <link>http://www.nicosteiner.de/</link>
    <description>Frontend-Technologien, Web Standards, Accessibility, SEO, Performance und Modularisierung</description>
    <dc:language>de</dc:language>
    <generator>Serendipity 1.4.1 - http://www.s9y.org/</generator>
    
    

<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/NicoSteiner-Portfolio" /><feedburner:info uri="nicosteiner-portfolio" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:browserFriendly></feedburner:browserFriendly><item>
    <title>What the fuck R U doing Dude?</title>
    <link>http://www.nicosteiner.de/archives/290-What-the-fuck-R-U-doing-Dude.html</link>
            <category>Skills</category>
    
    <comments>http://www.nicosteiner.de/archives/290-What-the-fuck-R-U-doing-Dude.html#comments</comments>
    <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=290</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=2.0&amp;type=comments&amp;cid=290</wfw:commentRss>
    

    <author>nospam@example.com (Nico Steiner)</author>
    <content:encoded>
    Kleines Firefox Addon Demo um einige häufig zu findende "Entwicklersünden" zu kommunizieren.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="https://github.com/nicosteiner/wtfrudd"&gt;Github WTFRUDD&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.thatsmysite.de/whiteboard-friday/impress-slides-misc/ff-addon-demo.html#/intro"&gt;Hier geht es zu der Präsentation&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Kurz zu den Technologien, die ich morgen beim Whiteboard Friday vorstellen werde:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="https://addons.mozilla.org/en-US/developers/docs/sdk/latest/dev-guide/tutorials/index.html#getting-started"&gt;Mozilla Addon SDK&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://git-scm.com/"&gt;git Windows Client&lt;/a&gt; (Klasse Seite zu git: &lt;a href="http://rogerdudler.github.com/git-guide/index.de.html"&gt;git Guide&lt;/a&gt;)&lt;br /&gt;
&lt;br /&gt;
&lt;a href="https://addons.mozilla.org/en-US/developers/docs/sdk/1.8/dev-guide/tutorials/getting-started-with-cfx.html"&gt;Getting started with cfx&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://support.mozilla.org/de/kb/firefox-profile-erstellen-und-loeschen"&gt;Firefox Profile erstellen&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href="https://addons.mozilla.org/en-US/developers/docs/sdk/latest/"&gt;Latest Mozilla SDK documentation&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Das Regelset ist sehr begrenzt. Es ist als Array von CSS-Selector-Strings hinterlegt und wird mit der entsprechenden JavaScript API geprüft.&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.w3.org/TR/2012/PR-selectors-api-20121213/"&gt;W3C Selectors API&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
So sieht das dann verkürzt aus:&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;WTFRUDD.Analyze.ruleset = [{&lt;br /&gt;
&lt;br /&gt;
    title: 'This dude thinks a11y is a girls name funny written!',&lt;br /&gt;
    &lt;br /&gt;
    rules: ['.label', '.headline', '.h1', '.h2', '.h3', '.bold', 'table .head', 'table .body', 'table .footer']&lt;br /&gt;
    &lt;br /&gt;
}, ...]&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Die einzelnen Regeln werden dann wie folgt geprüft:&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;if (document.querySelector(currentRuleset.rules[j])) ...&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Weiterhin habe ich als Prototyp "executable" Functions für komplexere Tests vorgesehen.&lt;br /&gt;
&lt;br /&gt;
Der Addon-Prototyp kann im Firefox hiermit installiert werden: &lt;a href="http://www.nicosteiner.de/uploads/wtfrudd.xpi" title="wtfrudd.xpi"&gt;wtfrudd.xpi&lt;/a&gt; (es kommt zu einem Warnhinweis, da ich das Addon über meinen privaten Webspace bereit stelle)&lt;br /&gt;
&lt;br /&gt;
Hier als Beispiel die Vodafone-Startseite, die momentan strong Tags mit Headline-Klassen verwendet.&lt;br /&gt;
&lt;br /&gt;
&lt;img class="serendipity_image_center" width="583" height="370" src="http://www.nicosteiner.de/uploads/vodafone-class-h2.png" alt="Vodafon h2 class" /&gt; 
    </content:encoded>

    <pubDate>Thu, 10 Jan 2013 21:54:01 +0100</pubDate>
    <guid isPermaLink="false">http://www.nicosteiner.de/archives/290-guid.html</guid>
    
</item>
<item>
    <title>Even more new SenSEO features</title>
    <link>http://www.nicosteiner.de/archives/289-Even-more-new-SenSEO-features.html</link>
            <category>Referenzen</category>
    
    <comments>http://www.nicosteiner.de/archives/289-Even-more-new-SenSEO-features.html#comments</comments>
    <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=289</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=2.0&amp;type=comments&amp;cid=289</wfw:commentRss>
    

    <author>nospam@example.com (Nico Steiner)</author>
    <content:encoded>
    New SenSEO version brings some more new features.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Check for Last-Modiefied header&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
Google says: "Make sure your web server supports the If-Modified-Since HTTP header. This feature allows your web server to tell Google whether your content has changed since we last crawled your site. Supporting this feature saves you bandwidth and overhead."&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://support.google.com/webmasters/bin/answer.py?hl=en&amp;answer=35769"&gt;Webmaster Guidelines&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Check for Content-Type header&lt;/li&gt;&lt;li&gt;Find alternative sitemap.xml path in robots.txt&lt;/li&gt;&lt;li&gt;Improved highlight feature&lt;/li&gt;&lt;li&gt;Some bugfixes&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
&lt;br /&gt;
The features will be available with the next SenSEO version 2.4.&lt;br /&gt;
&lt;br /&gt;
If you find bugs or have suggestions please post them at &lt;a href="https://getsatisfaction.com/senseo"&gt;Get Satisfaction&lt;/a&gt;. 
    </content:encoded>

    <pubDate>Thu, 29 Mar 2012 22:59:07 +0200</pubDate>
    <guid isPermaLink="false">http://www.nicosteiner.de/archives/289-guid.html</guid>
    
</item>
<item>
    <title>New SenSEO feature: Compare inspect results</title>
    <link>http://www.nicosteiner.de/archives/288-New-SenSEO-feature-Compare-inspect-results.html</link>
            <category>Referenzen</category>
    
    <comments>http://www.nicosteiner.de/archives/288-New-SenSEO-feature-Compare-inspect-results.html#comments</comments>
    <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=288</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=2.0&amp;type=comments&amp;cid=288</wfw:commentRss>
    

    <author>nospam@example.com (Nico Steiner)</author>
    <content:encoded>
    With the new version of SenSEO you are able to save an inspect result and compare it with the result of an other page.&lt;br /&gt;
&lt;br /&gt;
&lt;!-- s9ymdb:192 --&gt;&lt;img class="serendipity_image_left" width="614" height="384" src="http://www.nicosteiner.de/uploads/senseo-compare.png" alt="Compare inspect results" /&gt;&lt;br /&gt;
&lt;br /&gt;
The feature will be available with the next SenSEO version 2.4.&lt;br /&gt;
&lt;br /&gt;
If you find bugs or have suggestions please post them at &lt;a href="https://getsatisfaction.com/senseo"&gt;Get Satisfaction&lt;/a&gt;. 
    </content:encoded>

    <pubDate>Thu, 29 Mar 2012 22:55:04 +0200</pubDate>
    <guid isPermaLink="false">http://www.nicosteiner.de/archives/288-guid.html</guid>
    
</item>
<item>
    <title>New SenSEO feature: Pages crawler</title>
    <link>http://www.nicosteiner.de/archives/287-New-SenSEO-feature-Pages-crawler.html</link>
            <category>Referenzen</category>
    
    <comments>http://www.nicosteiner.de/archives/287-New-SenSEO-feature-Pages-crawler.html#comments</comments>
    <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=287</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=2.0&amp;type=comments&amp;cid=287</wfw:commentRss>
    

    <author>nospam@example.com (Nico Steiner)</author>
    <content:encoded>
    The pages crawler extracts all URLs from sitemap.xml and crawls these URLs. It ranks the pages based on the first keyword in keywords metatag.&lt;br /&gt;
&lt;br /&gt;
Klick image to view screenshot:&lt;br /&gt;
&lt;br /&gt;
&lt;a class='serendipity_image_link' href='http://www.nicosteiner.de/uploads/senseo-crawler.png'&gt;&lt;!-- s9ymdb:191 --&gt;&lt;img class="serendipity_image_left" width="110" height="65" src="http://www.nicosteiner.de/uploads/senseo-crawler.serendipityThumb.png" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
The ranking takes these rules into account:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;URL contains main keyword: &lt;strong&gt;+1&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;Title exists: &lt;strong&gt;+1&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;Title contains main keyword: &lt;strong&gt;+1&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;Description exists: &lt;strong&gt;+1&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;Description contains main keyword: &lt;strong&gt;+1&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
The crawling result is rendered into a table and will be available as an CSV export. For each page you can directly jump into the SenSEO inspect or components view.&lt;br /&gt;
&lt;br /&gt;
The feature will be available with the next SenSEO version 2.4.&lt;br /&gt;
&lt;br /&gt;
If you find bugs or have suggestions please post them at &lt;a href="https://getsatisfaction.com/senseo"&gt;Get Satisfaction&lt;/a&gt;. 
    </content:encoded>

    <pubDate>Thu, 29 Mar 2012 22:35:54 +0200</pubDate>
    <guid isPermaLink="false">http://www.nicosteiner.de/archives/287-guid.html</guid>
    
</item>
<item>
    <title>New SenSEO version is coming</title>
    <link>http://www.nicosteiner.de/archives/286-New-SenSEO-version-is-coming.html</link>
    
    <comments>http://www.nicosteiner.de/archives/286-New-SenSEO-version-is-coming.html#comments</comments>
    <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=286</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=2.0&amp;type=comments&amp;cid=286</wfw:commentRss>
    

    <author>nospam@example.com (Nico Steiner)</author>
    <content:encoded>
    In the next days I will finish work on a completely refactored version of SenSEO.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;SenSEO will bootstrap&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
SenSEO will no longer integrate into Firebug but will be, what Mozilla calls, a bootstrapped add-on.&lt;br /&gt;
&lt;br /&gt;
&lt;cite&gt;Bootstrapped add-ons are a special kind of add-on that developers can choose to use instead of normal add-ons in order to allow users to install and use the add-on without needing to restart the application.&lt;/cite&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;New features will come along&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;SenSEO will reopen with the last active tab.&lt;/li&gt;&lt;li&gt;Page load time is calculated with new &lt;a href="https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html"&gt;HTML5 Navigation Timing API&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;SenSEO is taking &lt;a href="http://support.google.com/webmasters/bin/answer.py?hl=en&amp;answer=176035"&gt;Microdata&lt;/a&gt; into account.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Some preview screenshots&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;!-- s9ymdb:188 --&gt;&lt;img class="serendipity_image_center" width="679" height="458" src="http://www.nicosteiner.de/uploads/senseo-preview-1.png" alt="SenSEO preview" /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;!-- s9ymdb:189 --&gt;&lt;img class="serendipity_image_center" width="677" height="456" src="http://www.nicosteiner.de/uploads/senseo-preview-2.png" alt="SenSEO preview" /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;!-- s9ymdb:190 --&gt;&lt;img class="serendipity_image_center" width="675" height="458" src="http://www.nicosteiner.de/uploads/senseo-preview-3.png" alt="SenSEO preview" /&gt;&lt;br /&gt;
&lt;br /&gt;
The refactored code in most cases is based on web technologies - don't nail me down on that, but this should make it easier to publish SenSEO on other platforms also.&lt;br /&gt;
&lt;br /&gt;
&lt;img src="http://admintell.napco.com/ee/images/uploads/gamertell/chrome-firefox-fight-ie-gives-up.jpg" alt="SenSEO for Chrome"&gt;&lt;br /&gt;
&lt;br /&gt;
If you find bugs (there will be some, the code is brand new), please report them on &lt;a href="http://getsatisfaction.com/senseo"&gt;getsatisfaction.com/senseo&lt;/a&gt;. 
    </content:encoded>

    <pubDate>Sun, 05 Feb 2012 01:31:56 +0100</pubDate>
    <guid isPermaLink="false">http://www.nicosteiner.de/archives/286-guid.html</guid>
    
</item>
<item>
    <title>Mini-Suchmaschine mit Frontend-Technologien</title>
    <link>http://www.nicosteiner.de/archives/285-Mini-Suchmaschine-mit-Frontend-Technologien.html</link>
            <category>Referenzen</category>
    
    <comments>http://www.nicosteiner.de/archives/285-Mini-Suchmaschine-mit-Frontend-Technologien.html#comments</comments>
    <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=285</wfw:comment>

    <slash:comments>2</slash:comments>
    <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=2.0&amp;type=comments&amp;cid=285</wfw:commentRss>
    

    <author>nospam@example.com (Nico Steiner)</author>
    <content:encoded>
    Die &lt;a href="http://www.sensational-seo.com/"&gt;SenSEO-Extension&lt;/a&gt; bekommt ein neues Feature "Analyze all pages". Hiermit soll es möglich sein, mit einem Klick die gesamte Website zu crawlen und sämtliche Seiten anhand vorgegebener Keywords zu bewerten. Dieses Crawlen und Bewerten wird ausschließlich mit Frontend-Technologien implementiert. Die nachfolgende Grafik zeigt die geplanten Schritte.&lt;br /&gt;
&lt;br /&gt;
&lt;!-- s9ymdb:187 --&gt;&lt;img width="708" height="637" src="http://www.nicosteiner.de/uploads/mini-crawler.png" alt="Mini-Searchengine" /&gt;&lt;br /&gt;
&lt;br /&gt;
Der Anfang ist bereits geschafft. Mit &lt;a href="http://www.sensational-seo.com/mini-searchengine/"&gt;diesem Prototypen&lt;/a&gt; (läuft nur im Firefox) ist es möglich, aus dem Markup einer vorgegebenen Seite sämtliche Links zu extrahieren. Es können lediglich Seiten von sensational-seo.com angegeben werden, da die &lt;a href="http://en.wikipedia.org/wiki/Same_origin_policy"&gt;Same Origin Policy&lt;/a&gt; nur Seiten der selben Domain für die Analyse zulässt.&lt;br /&gt;
&lt;br /&gt;
Das Markup wird mit der &lt;a href="http://www.w3.org/TR/XMLHttpRequest/ "&gt;XMLHttpRequest API&lt;/a&gt; abgerufen und mit der evaluate Function der Firefox &lt;a href="https://developer.mozilla.org/en/Introduction_to_using_XPath_in_JavaScript"&gt;XPath JavaScript API&lt;/a&gt; geparst.&lt;br /&gt;
&lt;br /&gt;
Da die API lediglich DOM Dokumente https://developer.mozilla.org/en/DOM/document verarbeitet, wird die als String gelieferte XMLHttpRequest Response vorher einem iFrame als Inhalt zugewiesen. Der folgende Code macht dies möglich.&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;// create iframe&lt;br /&gt;
var responseTextIframeElement = document.createElement('iframe');&lt;br /&gt;
responseTextIframeElement.setAttribute('width', '0');&lt;br /&gt;
responseTextIframeElement.setAttribute('height', '0');&lt;br /&gt;
responseTextIframe = document.body.appendChild(responseTextIframeElement);&lt;br /&gt;
responseTextIframe.contentWindow.document.write(responseText);&lt;br /&gt;
var responseXML = responseTextIframe.contentWindow.document;&lt;br /&gt;
// clear iframe&lt;br /&gt;
responseTextIframe.parentNode.removeChild(responseTextIframe);&lt;br /&gt;
mse.Crawler.gotPageContentByUrl(responseXML);&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Möchte man ohne XMLHttpRequest API arbeiten, kann man einem zuvor erzeugten iFrame auch einfach den URL als scr-Attribut zuweisen.&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;// create iframe&lt;br /&gt;
var responseTextIframeElement = document.createElement('iframe');&lt;br /&gt;
responseTextIframeElement.setAttribute('width', '0');&lt;br /&gt;
responseTextIframeElement.setAttribute('height', '0');&lt;br /&gt;
responseTextIframe = document.body.appendChild(responseTextIframeElement);&lt;br /&gt;
responseTextIframe.addEventListener('load', function(e) {&lt;br /&gt;
  var responseTextIframe = this;&lt;br /&gt;
  var responseXML = responseTextIframe.contentWindow.document;&lt;br /&gt;
  // clear iframe&lt;br /&gt;
  responseTextIframe.parentNode.removeChild(responseTextIframe);&lt;br /&gt;
  // this is not the best sollution&lt;br /&gt;
  mse.Crawler.gotPageContentByUrl(responseXML);&lt;br /&gt;
}, false);&lt;br /&gt;
responseTextIframe.src = url;        &lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Die Extrahierung der href-Attribute aus sämtlichen Anker-Tags übernimmt dann der folgende Code.&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;var allLinksXpath = responseXML.evaluate('/html/body//a/@href', responseXML, null, XPathResult.ANY_TYPE, null);&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
In einem nächsten Schritt sollen all die Verlinkungen extrahiert werden, welche absolut (mit http Schema) auf die selbe Domain verweisen oder Seiten relativ referenzieren. Diese Verlinkungen werden mit der &lt;a href="http://dev.w3.org/html5/webstorage/"&gt;Local Storage API&lt;/a&gt; auf einem Stack abgelegt und sequentiell nach dem LILO-Prinzip (Last in, Last out) gecrawlt. Dabei wird die Bereinigung von Dubletten mit Hilfe des &lt;a href="http://googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html"&gt;Canonical-Tag&lt;/a&gt; eine wichtige Rolle spielen. Im Local Storage wird neben der extrahierten URL also auch immer eine zweite kanonische URL abgelegt, welche durch einen entsprechenden Abgleich das doppelte Crawlen von Seiten verhindern soll. 
    </content:encoded>

    <pubDate>Mon, 24 Oct 2011 20:44:56 +0200</pubDate>
    <guid isPermaLink="false">http://www.nicosteiner.de/archives/285-guid.html</guid>
    
</item>
<item>
    <title>Rendern von Seiten-Komponenten</title>
    <link>http://www.nicosteiner.de/archives/284-Rendern-von-Seiten-Komponenten.html</link>
    
    <comments>http://www.nicosteiner.de/archives/284-Rendern-von-Seiten-Komponenten.html#comments</comments>
    <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=284</wfw:comment>

    <slash:comments>1</slash:comments>
    <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=2.0&amp;type=comments&amp;cid=284</wfw:commentRss>
    

    <author>nospam@example.com (Nico Steiner)</author>
    <content:encoded>
    Möchte man nur Teile einer Seite neu rendern, ohne den Rest der Seite zu verändern, bedient man sich häufig der DOM-Manipulation mit JavaScript. Sind an diesem Prozess dynamische Daten beteiligt, die auf dem Server gehalten werden, kommt auch noch XHR und JSON zum Austausch der Daten hinzu. Konkret ergeben sich daraus folgende Schritte, die für gewöhnlich als AJAX bezeichnet werden:&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Ein XHR-Request erfragt Daten vom Server, die dieser in einer Session hält&lt;/li&gt;&lt;li&gt;Der Server sendet die angeforderten Daten im JSON-Format und der Client wandelt diese in JavaScript-Objekte&lt;/li&gt;&lt;li&gt;Basierend auf den so entstandenen Objekten werden mit JavaScript Manipulationen am bestehenden HTML-Dokument vorgenommen&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Einige Nachteile dieses Vorgehens&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Der Ansatz funktioniert nur mit JavaScript - ohne JavaScript findet keine Veränderung des Dokuments statt&lt;/li&gt;&lt;li&gt;Eigens für die DOM-Manipulation muss JavaScript-Code geschrieben werden - auf eventuell bestehenden Code des Templatesystems auf dem Server kann nicht zurückgegriffen werden&lt;/li&gt;&lt;li&gt;Durch Punkt 2 besteht die Tendenz zum Duplizieren von Code in verschiedenen Sprachen auf Server- und Clientseite&lt;/li&gt;&lt;li&gt;Setzt man sehr massiv auf den oben beschriebenen Ansatz, sind für Suchmaschinen kaum verwertbare Inhalte verfügbar&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Wie können diese Nachteile umgangen werden?&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
Die meisten Templatesysteme setzen das HTML-Dokument aus einer Kombination verschiedener Seiten-Komponenten zusammen - typisch hierfür sind ein Header-, Content- und Footer-Bereich - aber auch Navigation, Sidebar etc. bilden solche Komponenten. Oft werden dynamische Daten genutzt, um z. B. eine Navigation zu erzeugen, die Links zu neu erzeugten Seiten generiert, ohne weitere Veränderungen am Code vorzunehmen zu müssen.&lt;br /&gt;
&lt;br /&gt;
Am Beispiel einer Kostenübersicht möchte ich demonstrieren, wie solch eine Komponente mit XHR nach jeder Veränderung des Warenkorbs ohne Neuladen der Seite aktualisiert werden kann. Der folgende Wireframe zeigt den schematisch Aufbau der Seite - links die zu aktualisierende Kostenübersicht, rechts der Bereich, über den Veränderungen am Warenkorb vorgenommen werden können.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;!-- s9ymdb:184 --&gt;&lt;img class="serendipity_image_center" width="500" height="425" style="border: 0px; margin: 0 auto;" src="http://www.nicosteiner.de/uploads/telesales-1.png" alt="Beispiel für eine Kostenübersicht" /&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Schritt 1 - Der initial Request&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
Der initiale Request ruft die Seite das erste Mal vom Server ab. Angenommen, es befinden sich zu diesem Zeitpunkt bereits zwei Artikel im Warenkorb, dann würde die Kostenübersicht von einer Komponente erzeugt werden, die für jeden der zwei Artikel eine neue Tabellenzeile mit den zugehörigen Daten generiert. Zusammen mit den übrigen Teilen der Seite entsteht ein komplettes HTML-Dokument, welches über HTTP an den Browser ausgeliefert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;!-- s9ymdb:185 --&gt;&lt;img class="serendipity_image_center" width="453" height="553" style="border: 0px; margin: 0 auto;" src="http://www.nicosteiner.de/uploads/html-xslt.png" alt="Initialer HTTP-Request" /&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
Soweit ist dies der klassische Ansatz, wie er von den meisten Frameworks verfolgt wird.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Schritt 2 - Ein Artikel wird hinzugefügt&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
Für das hinzufügen eines Artikels existiert ein Anker-Tag, welches einem Server-Script den neuen Artikel als GET-Paramter übergibt. Um das Neuladen der Seite zu verhindern, wird das Verhalten des Anker-Tags mit JavaScript unterbunden und statt dessen der Artikel über einen Webservice-Call mit XHR an den Server kommuniziert. Somit haben wir ein korrektes Verhalten für aktiviertes und deaktivertes JavaScript sichergestellt.&lt;br /&gt;
&lt;br /&gt;
In beiden Fällen wird dem Warenkorbsystem auf dem Server der ausgewählte Artikel hinzugefügt. Bei deaktiviertem JavaScript würde erneut ein HTML-Dokument mit dem neuen Artikel in der Kostenübersicht erzeugt und über HTTP an den Browser ausgeliefert werden. Das interessante Verhalten ergibt sich bei aktiviertem JavaScript. Nachdem der Webserivce-Call erfolgreich verarbeitet wurde, gilt es die Kostenübersicht zu aktualisieren. Beim klassischen AJAX-Ansatz würde die Response die neuen Warenkorb-Artikel enthalten und per DOM-Manipulation würde die Tabelle der Kostenübersicht um eine weitere Zeile ergänzt werden. Dies kann bei komplexeren Problemen schnell sehr aufwändig werden. Eine elegantere Lösung besteht darin, das HTML-Fragment der Kostenübersicht auf dem Server neu erzeugen zu lassen und anschließend das bestehende Fragment mit JavaScript durch das neu erzeugte zu ersetzten. Die folgende Grafik soll diese Lösung veranschaulichen.&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: center;"&gt;&lt;!-- s9ymdb:186 --&gt;&lt;img class="serendipity_image_center" width="500" height="318" style="border: 0px; margin: 0 auto;" src="http://www.nicosteiner.de/uploads/html-xslt-2.png" alt="Schaubild für HTML-Fragment" /&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Welche Probleme gibt es hierbei zu lösen&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
Es muss eine Verbindung vom alten zum neuen HTML-Fragment hergestellt werden können. Am einfachsten ist dies mit einer Element-ID möglich, über welche das Fragment identifiziert und durch das neue ersetzt werden kann. Weiterhin muss das serverseitige Templatesystem/Framework eine entsprechende Funktionalität zum selektiven Neurendern von Seitenkomponenten bereitstellen. Komponentenbasierte Frameworks bieten hier die besten Chancen für einen solchen Support. Eine weitere Herausforderung stellt das Erzeugen und Entfernen von Event-Listenern auf Elemente des Fragments dar - auch hier sollte das Framework eine entsprechende Unterstützung bieten. 
    </content:encoded>

    <pubDate>Mon, 01 Aug 2011 21:55:54 +0200</pubDate>
    <guid isPermaLink="false">http://www.nicosteiner.de/archives/284-guid.html</guid>
    
</item>
<item>
    <title>Hühnersuppe ala Mama</title>
    <link>http://www.nicosteiner.de/archives/283-Huehnersuppe-ala-Mama.html</link>
            <category>Rezepte</category>
    
    <comments>http://www.nicosteiner.de/archives/283-Huehnersuppe-ala-Mama.html#comments</comments>
    <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=283</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=2.0&amp;type=comments&amp;cid=283</wfw:commentRss>
    

    <author>nospam@example.com (Nico Steiner)</author>
    <content:encoded>
    Bei Erkältung hilft nur eins - die Hühnersuppe ala Mama. Die Zubereitung ist einfach und der &lt;a href="http://www.zeit.de/2003/11/Stimmts_H_9fhnersuppe" title="Suppentherapie Zeit-Online"&gt;Erkältung fällt dann auch nix mehr ein&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Folgende Zutaten werden für eine große Portion Hühnersuppe benötigt (bei einer kleineren Portion die halbe Menge oder fertig abgepacktes Suppengemüse kaufen):&lt;br /&gt;
&lt;br /&gt;
&lt;!-- s9ymdb:182 --&gt;&lt;img width="300" height="225" style="float: right; border: 0px; padding-left: 5px;" src="http://www.nicosteiner.de/uploads/huehnersuppe1.jpg" alt="Hühnersuppe ala Mama" /&gt;&lt;ul&gt;&lt;li&gt;1 großes Suppenhuhn vom Markt oder aus dem BIO-Laden&lt;/li&gt;&lt;li&gt;250g Suppennudeln&lt;/li&gt;&lt;li&gt;1 Kohlrabi&lt;/li&gt;&lt;li&gt;1 Butterrübe&lt;/li&gt;&lt;li&gt;1 Knolle Sellerie&lt;/li&gt;&lt;li&gt;2 mittelgroße Möhren&lt;/li&gt;&lt;li&gt;1 Stange Lauch&lt;/li&gt;&lt;li&gt;1 Bund Petersilie&lt;/li&gt;&lt;li&gt;Salz&lt;/li&gt;&lt;li&gt;Gemahlener schwarzer Pfeffer&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;
&lt;br /&gt;
Das Huhn ggf. auftauen und dann mit viel Wasser und reichlich Salz in einem großen Topf bei halb aufgelegtem Deckel zum Kochen bringen. Danach auf mittlere Hitze zurückschalten und weiter kochen lassen.&lt;br /&gt;
&lt;br /&gt;
Das Gemüse schälen und grob in größere Stücke zerteilen. Das Kleinschneiden kommt später. Beim Lauch gibt es zu beachten, dass auch die oberen, grünen Teile mitgekocht werden. Die Gemüsestücke zum Huhn in den Topf geben und ca. 20-30 Minuten gar kochen. Danach mit einer Schöpfkelle wieder aus dem Topf fischen (das Huhn kocht weiter), in eine Schüssel geben, klein schneiden und beiseite stellen. Je nach Geschmack nicht das gesamte Gemüse kleingeschneiden - von der Menge her ist das eher zu viel.&lt;br /&gt;
&lt;br /&gt;
Wenn das Huhn nach 1-2 Stunden gar gekocht ist (das Fleisch sollte sich ganz leicht vom Knochen lösen lassen) aus dem Topf nehmen, die Haut und die Knochen entfernen und das Hühnerfleisch in kleine Stücke schneiden. Parallel dazu Wasser mit einer Prise Salz in einem separaten Topf zum Kochen bringen und die Suppennudeln darin nach Anleitung kochen. Die Nudeln danach in ein feinmaschiges Sieb abgießen und zusammen mit den Fleischstücken und dem geschnitten Gemüse zurück in den Topf geben.&lt;br /&gt;
&lt;br /&gt;
Die Suppe mit Salz und Pfeffer abschmecken. Zum Schluss die Petersilie mit einem Wiegemesser klein schneiden und über die fertige Suppe streuen.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Ein paar Tipps&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
Suppe braucht viel Salz. Wenn trotzdem mal zu viel Salz an die Suppe gerät, hilft es, eine Kartoffel mitzukochen. Diese saugt das Salz auf und kann später weggeworfen werden.&lt;br /&gt;
&lt;br /&gt;
Wer die Suppe nicht ganz so fett mag, kann sie auch erst erkalten lassen, dann in den Kühlschrank stellen und nach einigen Stunden die Schicht Fett abziehen, die sich auf der Suppe bildet.&lt;br /&gt;
&lt;br /&gt;
Hühnersuppe läßt sich prima einfrieren. Größere Mengen am besten in Portionen aufteilen, da jedes erneute Aufkochen den Nudeln schadet. 
    </content:encoded>

    <pubDate>Mon, 01 Aug 2011 18:07:30 +0200</pubDate>
    <guid isPermaLink="false">http://www.nicosteiner.de/archives/283-guid.html</guid>
    
</item>
<item>
    <title>SenSEO Infografik</title>
    <link>http://www.nicosteiner.de/archives/282-SenSEO-Infografik.html</link>
    
    <comments>http://www.nicosteiner.de/archives/282-SenSEO-Infografik.html#comments</comments>
    <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=282</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=2.0&amp;type=comments&amp;cid=282</wfw:commentRss>
    

    <author>nospam@example.com (Nico Steiner)</author>
    <content:encoded>
    Zum 200.000sten Download von SenSEO habe ich als kleines Dankeschön eine Infografik mit interessanten Fakten zur Firefox-Extension zusammengestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;!-- s9ymdb:181 --&gt;&lt;img class="serendipity_image_center" width="725" height="575" src="http://www.nicosteiner.de/uploads/senseo-infographic.png" alt="SenSEO Infografik" /&gt; 
    </content:encoded>

    <pubDate>Tue, 05 Apr 2011 17:33:21 +0200</pubDate>
    <guid isPermaLink="false">http://www.nicosteiner.de/archives/282-guid.html</guid>
    
</item>
<item>
    <title>Gastartikel im Webstandard-Blog</title>
    <link>http://www.nicosteiner.de/archives/281-Gastartikel-im-Webstandard-Blog.html</link>
            <category>Referenzen</category>
    
    <comments>http://www.nicosteiner.de/archives/281-Gastartikel-im-Webstandard-Blog.html#comments</comments>
    <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=281</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=2.0&amp;type=comments&amp;cid=281</wfw:commentRss>
    

    <author>nospam@example.com (Nico Steiner)</author>
    <content:encoded>
    Gestern erschien im &lt;a href="http://webstandard.kulando.de/"&gt;Webstandard-Blog&lt;/a&gt; der erste von 3 Artikeln zur Verbesserung der Website-Performance mit Expires-Headern. Die Artikel basieren auf &lt;a href="http://stevesouders.com/hpws/"&gt;Steve Souders Veröffentlichungen&lt;/a&gt; und den praktischen Erfahrungen, die ich mit dem &lt;a href="http://www.nicosteiner.de/archives/275-Content-Delivery-Server-online!.html"&gt;Content Delivery Server&lt;/a&gt; gesammelt habe. Der zweite und dritte Teil folgen die nächsten Tage. 
    </content:encoded>

    <pubDate>Tue, 19 Oct 2010 16:50:43 +0200</pubDate>
    <guid isPermaLink="false">http://www.nicosteiner.de/archives/281-guid.html</guid>
    
</item>

</channel>
</rss>
