<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   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/"
   >
<channel>
    
    <title>Rodney Rehm</title>
    <link>https://blog.rodneyrehm.de/</link>
    <description>Webdevelopment, wherever it may take me…</description>
    <dc:language>en</dc:language>
    <generator>Serendipity 1.7.2 - http://www.s9y.org/</generator>
    <pubDate>Thu, 29 Sep 2016 08:05:24 GMT</pubDate>

    <image>
        <url>https://blog.rodneyrehm.de/templates/default/img/s9y_banner_small.png</url>
        <title>RSS: Rodney Rehm - Webdevelopment, wherever it may take me…</title>
        <link>https://blog.rodneyrehm.de/</link>
        <width>100</width>
        <height>21</height>
    </image>

<item>
    <title>You could have my day job</title>
    <link>https://blog.rodneyrehm.de/archives/41-You-could-have-my-day-job.html</link>
            <category>life</category>
    
    <comments>https://blog.rodneyrehm.de/archives/41-You-could-have-my-day-job.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=41</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=41</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;Ok, you can&#039;t have &lt;em&gt;my&lt;/em&gt; job, but one on my team. We currently have 3 open frontend development positions (&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/telekom.jobs/search/jobs/de/43034/Junior-Software-Entwickler-%28m%7Cw%29-Smart-Connected-Home/Berlin.html&#039;]);&quot;  href=&quot;https://telekom.jobs/search/jobs/de/43034/Junior-Software-Entwickler-%28m%7Cw%29-Smart-Connected-Home/Berlin.html&quot;&gt;junior&lt;/a&gt; to &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/telekom.jobs/search/jobs/de/44294/Senior-Software-Entwickler-%28m%7Cw%29-Smart-Connected-Home/Berlin.html&#039;]);&quot;  href=&quot;https://telekom.jobs/search/jobs/de/44294/Senior-Software-Entwickler-%28m%7Cw%29-Smart-Connected-Home/Berlin.html&quot;&gt;senior&lt;/a&gt;). In this post I&#039;ll outline my life at Deutsche Telekom to give you an impression of what working here is like. I&#039;m not exactly a fan of &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/telekom.jobs/search/jobs/de/44294/Senior-Software-Entwickler-%28m%7Cw%29-Smart-Connected-Home/Berlin.html&#039;]);&quot;  href=&quot;https://telekom.jobs/search/jobs/de/44294/Senior-Software-Entwickler-%28m%7Cw%29-Smart-Connected-Home/Berlin.html&quot;&gt;official job descriptions&lt;/a&gt;. In fact, I wouldn&#039;t apply to them myself. While I can&#039;t do anything about that careers &quot;website&quot;, I &lt;em&gt;can&lt;/em&gt; share some insight…&lt;/p&gt;

&lt;h2&gt;My story&lt;/h2&gt;

&lt;p&gt;Let&#039;s start at the beginning. About 5 years ago I got to know &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/twitter.com/asciidisco&#039;]);&quot;  href=&quot;http://twitter.com/asciidisco&quot;&gt;Sebastian Golasch&lt;/a&gt; at a conference&#039;s dinner. That evening I declared that I would &lt;em&gt;never ever&lt;/em&gt; work for Deutsche Telekom, after listening to a Freelancer rant about working on a Deutsche Telekom project. A few months later I was contracting on a Deutsche Telekom project. A year later I gave up 10 years of freelance and became a full-time &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/en.wikipedia.org/wiki/Magenta&#039;]);&quot;  href=&quot;https://en.wikipedia.org/wiki/Magenta&quot;&gt;magenta&lt;/a&gt; employee. I&#039;ve been working on this product for 4 years and at the company for 3 years and &lt;strong&gt;I have no intention of leaving&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;My motivation&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;I&#039;ve always wanted to empower people.&lt;/strong&gt; For the first half of the last decade that meant empowering not-very-technical mid-level managers to manage electronic workflows and data structures. While I certainly learned a lot doing that, I wasn&#039;t particularly connected to the product or its users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I&#039;ve always been a fan of misappropriation&lt;/strong&gt; (today we&#039;d call it &quot;hacking&quot;): Modifying tools (software, physical objects) so they can be used for tasks they were not originally designed for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I grew up with Lego&lt;/strong&gt; and I write software, so it&#039;s natural to think in small (insignificant) blocks that, when combined, solve a problem.&lt;/p&gt;

&lt;p&gt;I&#039;ve found all of that working on this product. A product that actually &lt;em&gt;can&lt;/em&gt; change people&#039;s lives in ways we may not even understand yet.&lt;/p&gt;

&lt;h3&gt;My status quo&lt;/h3&gt;

&lt;p&gt;When I joined the product I saw a number of problems with how things were done (or not done at all). These problems weren&#039;t necessarily of technical nature. I wasn&#039;t happy with how the product was built. The separation of concerns (on a team level) was wrong. A few things looked like a pile of duct-tape spaghetti. The user experience wasn&#039;t great (euphemism). Communication and collaboration wasn&#039;t a thing. And. So. On.&lt;/p&gt;

&lt;p&gt;I&#039;m happy to report that most of these issues have been squatted since then. 4 years ago we were in &quot;startup&quot; mode, meaning we tried to get things done &lt;em&gt;quick&lt;/em&gt;, rather than &lt;em&gt;well&lt;/em&gt;. Today we&#039;ve curbed the &quot;quick&quot; and (mostly) focus on the &quot;well&quot;.&lt;/p&gt;

&lt;p&gt;It certainly wasn&#039;t &lt;em&gt;me&lt;/em&gt; improving all of that, but I&#039;ve had a (Trump-sized) hand in a few of those topics. This led to a certain feeling of ability to improve things for us, the product and the consumer - and that&#039;s what&#039;s keeping me entertained.&lt;/p&gt;

&lt;p&gt;Enough narcissism, let&#039;s get to what we work on and how we do that…&lt;/p&gt;

&lt;h2&gt;What we work on&lt;/h2&gt;

&lt;p&gt;The general topic is &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/en.wikipedia.org/wiki/Internet_of_things&#039;]);&quot;  href=&quot;https://en.wikipedia.org/wiki/Internet_of_things&quot;&gt;IoT (Internet of Things)&lt;/a&gt;. My team builds the customer facing web frontends of the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.qivicon.com/en/&#039;]);&quot;  href=&quot;https://www.qivicon.com/en/&quot;&gt;Qivicon Platform&lt;/a&gt; which is the base of Deutsche Telekom&#039;s &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.smarthome.de/&#039;]);&quot;  href=&quot;https://www.smarthome.de/&quot;&gt;Magenta Smart Home&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We connect &quot;everyday objects&quot; (e.g. &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www2.meethue.com/&#039;]);&quot;  href=&quot;http://www2.meethue.com/&quot;&gt;Philips Hue&lt;/a&gt;, &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.netatmo.com/&#039;]);&quot;  href=&quot;https://www.netatmo.com/&quot;&gt;Netatmo&lt;/a&gt;, &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.eq-3.de/&#039;]);&quot;  href=&quot;http://www.eq-3.de/&quot;&gt;eQ-3&lt;/a&gt;, and lots more) and allow them to communicate with each other. Since these &quot;smart devices&quot; &lt;em&gt;can&lt;/em&gt; be rather dumb, it&#039;s the web UI&#039;s job to make this stuff as simple as possible. In the end we take care of all the UIs for maintaining a smart home.&lt;/p&gt;

&lt;p&gt;This product allows people to rewire how their home works - and &lt;em&gt;we&lt;/em&gt; are making sure that it&#039;s managable by people without a degree in computer science.&lt;/p&gt;

&lt;h2&gt;The tools we use&lt;/h2&gt;

&lt;p&gt;We have a number of legacy apps built on top of &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/backbonejs.org/&#039;]);&quot;  href=&quot;http://backbonejs.org/&quot;&gt;Backbone&lt;/a&gt; and &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/marionettejs.com/&#039;]);&quot;  href=&quot;http://marionettejs.com/&quot;&gt;Marionette&lt;/a&gt;. New projects are starting with &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/vuejs.org/&#039;]);&quot;  href=&quot;https://vuejs.org/&quot;&gt;Vue.js&lt;/a&gt;. We&#039;re planning to gradually move everything over to Vue - and this is something you&#039;d be working on with us. But changing stacks like that takes time, so you&#039;d also help us maintain the legacy apps until they&#039;re converted.&lt;/p&gt;

&lt;p&gt;The legacy apps use &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/gruntjs.com/&#039;]);&quot;  href=&quot;http://gruntjs.com/&quot;&gt;grunt&lt;/a&gt; and other prehistoric tools. The Vue stack is built on top of &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/webpack/webpack&#039;]);&quot;  href=&quot;https://github.com/webpack/webpack&quot;&gt;Webpack&lt;/a&gt; and offers some of the modern amenities that instantly make you a 10X developer, simply by knowing their names.&lt;/p&gt;

&lt;p&gt;We are big proponents of web technology, meaning we favor standards like &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/developer.mozilla.org/en-US/docs/Web/Web_Components&#039;]);&quot;  href=&quot;https://developer.mozilla.org/en-US/docs/Web/Web_Components&quot;&gt;Web Components&lt;/a&gt; over things like React and JSX. If you&#039;re looking for Angular, React, Ember or whatever today&#039;s framework is, stop reading. You won&#039;t be chasing the newest hottest tools with us.&lt;/p&gt;

&lt;p&gt;We manage our code in &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/git-scm.com/&#039;]);&quot;  href=&quot;https://git-scm.com/&quot;&gt;git repositories&lt;/a&gt; powered by &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.atlassian.com/software/bitbucket&#039;]);&quot;  href=&quot;https://www.atlassian.com/software/bitbucket&quot;&gt;Bitbucket&lt;/a&gt; (formerly Stash).&lt;/p&gt;

&lt;p&gt;While the frontend stack pretty much is all JavaScript, we&#039;re part of a Java ecosystem. None of us frontend developers really do &lt;em&gt;any&lt;/em&gt; Java, but we are &lt;em&gt;using&lt;/em&gt; things like &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/maven.apache.org/&#039;]);&quot;  href=&quot;http://maven.apache.org/&quot;&gt;Maven&lt;/a&gt; and &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.sonatype.org/nexus/&#039;]);&quot;  href=&quot;http://www.sonatype.org/nexus/&quot;&gt;Nexus&lt;/a&gt;. Some parts of a website we maintain is written in &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/php.net/&#039;]);&quot;  href=&quot;http://php.net/&quot;&gt;PHP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Everyone uses the editor or IDE they want. Some use a GUI for git, but most of us prefer the command line for git (and anything, really). Ultimately you&#039;re free to choose the tools you feel comfortable with.&lt;/p&gt;

&lt;p&gt;Pretty much everyone here works on a MacBookPro. If you prefer Linux or Windows, you can have that, too.&lt;/p&gt;

&lt;h2&gt;Team work&lt;/h2&gt;

&lt;p&gt;Currently we&#039;re 4 frontend developers, 2 designers, 3 QA engineers, 1 product owner and 1 scrum master. And we&#039;re looking for 3 additional frontend developers.&lt;/p&gt;

&lt;p&gt;We&#039;re split between Germany and Bulgaria. Ze Germans work in Darmstadt. Some are here for 3 days a week, working 2 from home. Some are here all the time - because they happen to actually live in Darmstadt. We also have offices in Bonn and Berlin, which could be used if you don&#039;t feel like Darmstadt is your city. We try to see everyone at the office on Tuesday and Wednesday.&lt;/p&gt;

&lt;p&gt;The team communicates (in English) via chat and video conferencing. Official meetings are usually done with &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.webex.com/&#039;]);&quot;  href=&quot;https://www.webex.com/&quot;&gt;WebEx&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We manage our work with &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.atlassian.com/software/jira&#039;]);&quot;  href=&quot;https://www.atlassian.com/software/jira&quot;&gt;Jira&lt;/a&gt; and document things in &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.atlassian.com/software/confluence&#039;]);&quot;  href=&quot;https://www.atlassian.com/software/confluence&quot;&gt;Confluence&lt;/a&gt;. We generally try to avoid mail.&lt;/p&gt;

&lt;h2&gt;Development process&lt;/h2&gt;

&lt;p&gt;We currently work in &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/en.wikipedia.org/wiki/Kanban_%28development%29&#039;]);&quot;  href=&quot;https://en.wikipedia.org/wiki/Kanban_%28development%29&quot;&gt;Kanban&lt;/a&gt; and some of the other teams work in &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/en.wikipedia.org/wiki/Scrum_%28software_development%29&#039;]);&quot;  href=&quot;https://en.wikipedia.org/wiki/Scrum_%28software_development%29&quot;&gt;Scrum&lt;/a&gt; mode. Our process looks as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Designers create their proposals consulting with developers early on.&lt;/li&gt;
&lt;li&gt;Developers implement things, usually doing another dance with designers.&lt;/li&gt;
&lt;li&gt;Implementation ends with a code review (pull requests via Bitbucket).&lt;/li&gt;
&lt;li&gt;Once the product owner signs off, our QA engineers go to work creating automated tests and manually run things in various browsers.&lt;/li&gt;
&lt;li&gt;If the testers don&#039;t find any issues (haha, of course they always do!), our code is delivered to the next stage of QA.&lt;/li&gt;
&lt;li&gt;The central QA team runs another round of extensive end to end tests on all of the product&#039;s systems on a platform similar to the production servers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our sprint cycle is 2 weeks. With the QA team &quot;lagging behind&quot; by 1 sprint, our software reaches the customer approximately 1 month after we&#039;ve written it.&lt;/p&gt;

&lt;p&gt;We&#039;re working in these stages for a reason. In development and integration we have access to pretty much everything. In production we have access to &lt;em&gt;nothing&lt;/em&gt;. We have to go through the proper channels to obtain log fragments from production servers. Data privacy is kind of a big deal around here.&lt;/p&gt;

&lt;p&gt;To web developers accustomed to creating web sites the staging concept and the two instances of QA may seem a bit odd. But in a system where your customers&#039; well-being can be at stake, you just can&#039;t have enough QA. And even with our setup lots of issues fall through - because this stuff is getting real complex real fast.&lt;/p&gt;

&lt;h2&gt;What about open source?&lt;/h2&gt;

&lt;p&gt;The system is based on &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.eclipse.org/smarthome/&#039;]);&quot;  href=&quot;https://www.eclipse.org/smarthome/&quot;&gt;eclipse smarthome&lt;/a&gt;. The project&#039;s lead sits in shouting distance. Our Runtime team contributes &lt;em&gt;extensively&lt;/em&gt;. They also work on other projects like &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/jupnp/jupnp&#039;]);&quot;  href=&quot;https://github.com/jupnp/jupnp&quot;&gt;jUPnP&lt;/a&gt; and &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/jmdns/jmdns&#039;]);&quot;  href=&quot;https://github.com/jmdns/jmdns&quot;&gt;JmDNS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The frontend developers don&#039;t have any official projects like that. But we&#039;ve created and shared (and maintain) the odd project like &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/timonreinhard/wemo-client&#039;]);&quot;  href=&quot;https://github.com/timonreinhard/wemo-client&quot;&gt;wemo-client&lt;/a&gt;, &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/allyjs.io/&#039;]);&quot;  href=&quot;http://allyjs.io/&quot;&gt;ally.js&lt;/a&gt;, &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/medialize/sass.js/&#039;]);&quot;  href=&quot;https://github.com/medialize/sass.js/&quot;&gt;sass.js&lt;/a&gt;, &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/rodneyrehm/viewport-units-buggyfill&#039;]);&quot;  href=&quot;https://github.com/rodneyrehm/viewport-units-buggyfill&quot;&gt;viewport-units-buggyfill&lt;/a&gt; and more. A couple of years ago, when we were unhappy with how we write tests, Sebastian created &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/dalekjs.com/&#039;]);&quot;  href=&quot;http://dalekjs.com/&quot;&gt;DalekJS&lt;/a&gt;. And of course we&#039;ve contributed bug fixes to most of the tools in our stack.&lt;/p&gt;

&lt;h2&gt;What are the perks?&lt;/h2&gt;

&lt;p&gt;We&#039;re not really into foosball tables and stuff like that - so, none of that &quot;useless frathouse fun stuff&quot;, sorry. There&#039;s all-you-can-drink coffee, water and tea. If you need pop soda, candy or similar, get some at the kiosk downstairs. I&#039;m not sure what to tell you here. I&#039;ve seen Google&#039;s and Facebook&#039;s offices. While it &lt;em&gt;sounds&lt;/em&gt; fun, I&#039;ve never missed any of that.&lt;/p&gt;

&lt;p&gt;Conference-wise we have different situations. Some of us attend one conference a year, with expenses covered by Deutsche Telekom. Others attend a &lt;em&gt;few&lt;/em&gt; more and get that time off, but cover the expenses themselves. In 2016 I&#039;ll have attended &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/profile/rodneyrehm/2016/&#039;]);&quot;  href=&quot;http://lanyrd.com/profile/rodneyrehm/2016/&quot;&gt;8 conferences&lt;/a&gt;). We&#039;d be happy to take you along the ride :)&lt;/p&gt;

&lt;p&gt;I think everyone has 30 days of vacation. Past 22:00 nobody gets into the office anymore because we shouldn&#039;t be working anymore anyway. We&#039;re told to work sustainable hours. It&#039;s up to us, nobody checks when or how much we really work. But if someone realizes that you&#039;re putting in too many hours, you&#039;ll be called out on that and asked to take more care of yourself.&lt;/p&gt;

&lt;p&gt;I&#039;m not saying there&#039;s no pressure to deliver things, but I haven&#039;t had to pull an all-nighter since I began working here in 2013. Things are done when they&#039;re done. While we &lt;em&gt;may&lt;/em&gt; be asked to make something work by a certain deadline, it&#039;s far more common to push the deadline or re-define scope of delivery. People are here to create a great product, not to burn out.&lt;/p&gt;

&lt;h2&gt;Why this job is important&lt;/h2&gt;

&lt;p&gt;Smart Home and Internet of Things are fairly new consumer markets. Technology and devices have been around for a while, but emerged in silos and often with questionable user experience.&lt;/p&gt;

&lt;p&gt;The product we work on is focused on breaking or connecting these silos. Our team is responsible for making the management of these connected devices as intuitive and easy as possible. We empower people with limited technical skills to accomplish technical tasks. We make this stuff &lt;em&gt;usable&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;What you&#039;ll learn on this job&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;I&#039;ll be pestering you with semantic html, accessibility, CSS, debugging and understanding browsers. We&#039;re working &lt;em&gt;with&lt;/em&gt; the &quot;Web Platform&quot;, and that means understanding it.&lt;/li&gt;
&lt;li&gt;Sebastian will be annoying you with the newest technologies and performance tricks. We&#039;re working in a realm of constant change. While we don&#039;t adopt every new technology right away, we do need to be aware of them.&lt;/li&gt;
&lt;li&gt;Timon will share his thoughts on how to write clean and maintainable code. We don&#039;t create projects that will be re-created from scratch by another agency 3 years down the road.&lt;/li&gt;
&lt;li&gt;You&#039;ll learn that we have things to learn from you, too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We transfer knowledge mostly through comments on pull requests. Also we have an hourly cigarette break that we use to catch each other up and pick each other&#039;s brains. (Not everyone smokes during these breaks, though ;)&lt;/p&gt;

&lt;h2&gt;What now?&lt;/h2&gt;

&lt;p&gt;If you&#039;re interested in what we&#039;re doing and how we&#039;re doing it, consider working with us!&lt;/p&gt;

&lt;p&gt;On &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/telekom.jobs/global-careers&#039;]);&quot;  href=&quot;https://telekom.jobs/global-careers&quot;&gt;Telekom Careers&lt;/a&gt; search for &quot;Smart Home&quot; and chose the profile that suits you best (&quot;Software Entwickler&quot; also applies to the frontend positions). If German isn&#039;t your language, or you have questions, &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/twitter.com/rodneyrehm&#039;]);&quot;  href=&quot;https://twitter.com/rodneyrehm&quot;&gt;ping me on twitter&lt;/a&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;Twitter pings&lt;/h2&gt;

&lt;p&gt;These questions popped up on twitter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Do I need to know JavaScript?&lt;/strong&gt; Yes. It&#039;s about 80% of what you write. We create reusable components, that once done mean we don&#039;t have to touch the HTML or CSS anymore. You won&#039;t need to invert a binary tree on a whiteboard, but you definitely need to know your way around JS.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Can I work from remote?&lt;/strong&gt; Yes and no. As an employee of Deutsche Telekom you need to be &quot;stationed&quot; at one of its offices. In our case that&#039;s Berlin, Bonn or Darmstadt, where you&#039;ll have to spend 2-3 days of the week. (I don&#039;t live in either of these cities, but not everyone is comfy with living in hotels…)&lt;/li&gt;
&lt;/ul&gt;
 
    </content:encoded>

    <pubDate>Wed, 28 Sep 2016 22:44:00 +0200</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/41-guid.html</guid>
    
</item>
<item>
    <title>jQuery ContextMenu Is Moving On</title>
    <link>https://blog.rodneyrehm.de/archives/40-jQuery-ContextMenu-Is-Moving-On.html</link>
            <category>life</category>
    
    <comments>https://blog.rodneyrehm.de/archives/40-jQuery-ContextMenu-Is-Moving-On.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=40</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=40</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;On July 7th 2011 I published my first &quot;serious&quot; jQuery plugin - a context menu manager. Today, 4 years later, I&#039;m waving good bye and wishing it the best of luck on its upcoming journey with its new maintainers from &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.swis.nl/&#039;]);&quot;  href=&quot;http://www.swis.nl/&quot;&gt;swis.nl&lt;/a&gt;.
 In 2011 I was working on an application where a &lt;em&gt;lot&lt;/em&gt; of UI elements needed to expose a context menu and none of the then &quot;state of the art&quot; jQuery plugins could handle the load. So I did what anyone does in that situation and created a new plugin. Back then HTML5 was still new, in flux and exciting and I wanted to make something that was along the lines of &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/developer.mozilla.org/en-US/docs/Web/HTML/Element/menu&#039;]);&quot;  href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/menu&quot;&gt;&lt;code&gt;&amp;lt;menu&amp;gt;&lt;/code&gt;&lt;/a&gt; (which did not make it into HTML5, but is part of &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.w3.org/TR/html51/semantics.html#the-menu-element&#039;]);&quot;  href=&quot;http://www.w3.org/TR/html51/semantics.html#the-menu-element&quot;&gt;HTML5.1&lt;/a&gt;). With a little help by &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/addyosmani.com/&#039;]);&quot;  href=&quot;http://addyosmani.com/&quot;&gt;Addy Osmani&lt;/a&gt; my plugin was able to act as a polyfill and work with the &quot;native context menu&quot; implementation in Firefox. Features were added and the interest in the plugin grew. Over the course of 3 years almost 50 versions got released. And then I lost interest.&lt;/p&gt;

&lt;p&gt;In late 2012 I abandoned the software I needed the context menu plugin for. Until January 2013 I kept maintaining the plugin and pushing updates without having any use for it myself. And then I realized that I did not have time to maintain software, that I did not use myself, for other people for free. I stopped maintaining the plugin, stopped replying to issues or looking at pull requests. On May 21st 2015 I decided things had gotten too hairy for anyone to use this plugin and put up a notice that the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/swisnl/jQuery-contextMenu/issues/257&#039;]);&quot;  href=&quot;https://github.com/swisnl/jQuery-contextMenu/issues/257&quot;&gt;project was looking for a new maintainer&lt;/a&gt;. At that point some 89 issues and 27 pull requests were hanging high and dry. I needed a way out of the &quot;obligation to maintain my software&quot;, and the notice did the job of clearing my conscience.&lt;/p&gt;

&lt;p&gt;Last week &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/bbrala&#039;]);&quot;  href=&quot;https://github.com/bbrala&quot;&gt;Björn Brala&lt;/a&gt; of &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.swis.nl/&#039;]);&quot;  href=&quot;http://www.swis.nl/&quot;&gt;swis.nl&lt;/a&gt; got in touch and informed me of their interest to take over the project. He made sure there was a budget for maintaining the project beforehand. And made clear that they were not looking to commercialize the project itself, but continue maintaining it open source, so they could continue using it in their commercial projects.&lt;/p&gt;

&lt;p&gt;Today we transferred the repository to its &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/swisnl/jQuery-contextMenu/&#039;]);&quot;  href=&quot;https://github.com/swisnl/jQuery-contextMenu/&quot;&gt;new home&lt;/a&gt; in the swisnl organization. The change-free version 1.6.8 has been published to bower and &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.npmjs.com/package/jquery-contextmenu&#039;]);&quot;  href=&quot;https://www.npmjs.com/package/jquery-contextmenu&quot;&gt;npm&lt;/a&gt; and a few &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/medialize/medialize.github.com/tree/master/jQuery-contextMenu&#039;]);&quot;  href=&quot;https://github.com/medialize/medialize.github.com/tree/master/jQuery-contextMenu&quot;&gt;gh-pages redirects&lt;/a&gt; will make sure that existing links to the project&#039;s website find their way to the new home. As of today Björn and the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/swisnl&#039;]);&quot;  href=&quot;https://github.com/swisnl&quot;&gt;swisnl&lt;/a&gt; team are the owners and maintainers of &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/swisnl/jQuery-contextMenu/&#039;]);&quot;  href=&quot;https://github.com/swisnl/jQuery-contextMenu/&quot;&gt;jQuery-contextMenu&lt;/a&gt;. I wish you the best of luck with your new project!&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Tue, 18 Aug 2015 19:20:35 +0200</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/40-guid.html</guid>
    
</item>
<item>
    <title>Presentations Involving Physical Things</title>
    <link>https://blog.rodneyrehm.de/archives/39-Presentations-Involving-Physical-Things.html</link>
            <category>life</category>
    
    <comments>https://blog.rodneyrehm.de/archives/39-Presentations-Involving-Physical-Things.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=39</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=39</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;Let&#039;s assume you&#039;re in a situation where you have to show a physical object during a presentation to 20 or more people. The current default is showing a static picture of the thing on the projector and possibly holding up the real thing so the first few rows of the audience might get a glimpse. What if I told you there&#039;s a better way? Working in the &lt;em&gt;Internet Of Things&lt;/em&gt; segment, I&#039;m constantly dealing with, well, a lot of &lt;em&gt;things&lt;/em&gt;. Those things tend to be small enough to fit in my hands. Considering we&#039;re &quot;agile&quot; (whatever that means to you), we have to present our work in two week intervals. Considering we&#039;re a distributed team, we live-stream those presentations all over the place. People may be sitting in one of three offices or even their homes while passively watching - or actively giving - the presentation.&lt;/p&gt;

&lt;p&gt;In our biweekly reviews we use &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.webex.com/&#039;]);&quot;  href=&quot;http://www.webex.com/&quot;&gt;WebEx&lt;/a&gt;, in ad-hoc presentations we may use &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/plus.google.com/hangouts/&#039;]);&quot;  href=&quot;https://plus.google.com/hangouts/&quot;&gt;Google Hangouts&lt;/a&gt; or &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/appear.in/&#039;]);&quot;  href=&quot;https://appear.in/&quot;&gt;appear.in&lt;/a&gt; or &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/skype.com/&#039;]);&quot;  href=&quot;http://skype.com/&quot;&gt;Skype&lt;/a&gt; or whatever tool we could settle on. Most of us use macs, some are on Windows and everyone has an iPhone or some Android phone.&lt;/p&gt;

&lt;p&gt;The goal is to stream what&#039;s happening in the room along with the actual presentation content to both, the projector and the remote client. The constraints are uncertain video conference tool and lack of specialized hardware. The solution is so simple, it took us &lt;em&gt;ages&lt;/em&gt; to figure it out.&lt;/p&gt;

&lt;p&gt;We&#039;re streaming our phone&#039;s camera image to our computer screens, which in turn end up on the projector and the remote client. In some scenarios you can manage this with built in mechanisms, in other situations you&#039;ll want to buy a $15 license for &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.airsquirrels.com/reflector/&#039;]);&quot;  href=&quot;http://www.airsquirrels.com/reflector/&quot;&gt;ReflectorApp&lt;/a&gt;. All you need to do is start the application on your computer, make your phone mirror its screen (using AirPlay, Google Cast, …) and open the phone&#039;s camera app. Et voila: instant wireless, handheld video camera that allows you to include the real-world in your presentation. It&#039;s so simple, it almost hurts.&lt;/p&gt;

&lt;p&gt;Granted, we haven&#039;t used this technique particularly often and not at all in months. It&#039;s at conferences that I get reminded of this idea time and time again. I try to talk to the speakers after their shows containing little things on stage that nobody could see past the fifth row and explain that I couldn&#039;t &lt;em&gt;see&lt;/em&gt; what they were showing off. Never mind the people watching the videos of the talks will likely not see all that much either. The discussion usually ends in a good laugh about not seeing the obvious: using your phone as a mobile camera to get your physical interactions on the big screen.&lt;/p&gt;

&lt;p&gt;The same thing happened again just now - finally prompting me to write this post. I saw &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/twitter.com/timpietrusky&#039;]);&quot;  href=&quot;https://twitter.com/timpietrusky&quot;&gt;Tim Pietrusky&lt;/a&gt; showing his &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/twitter.com/nerddisco&#039;]);&quot;  href=&quot;https://twitter.com/nerddisco&quot;&gt;NERDDISCO&lt;/a&gt; at &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/karlsruhejs.org/&#039;]);&quot;  href=&quot;http://karlsruhejs.org/&quot;&gt;KarlsruheJS&lt;/a&gt;, luckily I was sitting in the first row and filmed a bit of what I was seeing&lt;/p&gt;

&lt;p&gt;	
&lt;div class=&quot;serendipity_oembed_video&quot;&gt;
&lt;iframe width=&quot;550&quot; height=&quot;309&quot; src=&quot;https://www.youtube.com/embed/aDu-aZ3DRAk?feature=oembed&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/p&gt;

&lt;p&gt;The show was partly about what was being projected - a web browser&#039;s canvas reacting to some audio and getting additional input from a midi device - and the comparably tiny LED cube Tim built and programmed to visualize sections of the browser&#039;s canvas. Tim created some fantastic stuff right there. His show was a far cry from bad. But people sitting away 15m from the pedestal couldn&#039;t enjoy what I was seeing.&lt;/p&gt;

&lt;p&gt;Here&#039;s a screenshot of how streaming your phone&#039;s camera to your computer screen might look in real life.&lt;/p&gt;

&lt;div class=&quot;serendipity_imageComment_center&quot; style=&quot;width: 800px&quot;&gt;&lt;div class=&quot;serendipity_imageComment_img&quot;&gt;&lt;!-- s9ymdb:21 --&gt;&lt;img class=&quot;serendipity_image_center&quot; width=&quot;800&quot;  src=&quot;https://blog.rodneyrehm.de/uploads/reflector/reflector-screen-mirroring.png&quot;  alt=&quot;Phone&#039;s camera mirrored onto computer screen&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;serendipity_imageComment_txt&quot;&gt;Phone&#039;s camera mirrored onto computer screen&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ignore the camera app&#039;s interface and focus on the content. Ignore that you&#039;ll have to leave your fullscreen presentation for a moment. Ignore the little imperfections and focus on what you just gained: Everyone is able to see. A screencast will contain not only the presentation, but also the real life thing.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sat, 13 Jun 2015 16:36:48 +0200</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/39-guid.html</guid>
    
</item>
<item>
    <title>You may not need localtunnel or ngrok</title>
    <link>https://blog.rodneyrehm.de/archives/38-You-may-not-need-localtunnel-or-ngrok.html</link>
            <category>shell</category>
    
    <comments>https://blog.rodneyrehm.de/archives/38-You-may-not-need-localtunnel-or-ngrok.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=38</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=38</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;It&#039;s become a custom amongst web developers to write »you may not need $insert_tool« posts. Continuing with that tradition, here&#039;s my stab at why you might not need &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/localtunnel.me/&#039;]);&quot;  href=&quot;http://localtunnel.me/&quot;&gt;localtunnel.me&lt;/a&gt; and &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/ngrok.com/&#039;]);&quot;  href=&quot;https://ngrok.com/&quot;&gt;ngrok.com&lt;/a&gt;. Today&#039;s tool in question:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/defunctzombie/localtunnel&#039;]);&quot;  href=&quot;https://github.com/defunctzombie/localtunnel&quot;&gt;localtunnel&lt;/a&gt; exposes your localhost to the world for easy testing and sharing! No need to mess with DNS or deploy just to have others test out your changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As naming things is hard, we have a JavaScript &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/defunctzombie/localtunnel&#039;]);&quot;  href=&quot;https://github.com/defunctzombie/localtunnel&quot;&gt;localtunnel&lt;/a&gt; via npm, a python &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/swistaczek/localtunnel&#039;]);&quot;  href=&quot;https://github.com/swistaczek/localtunnel&quot;&gt;localtunnel&lt;/a&gt; via &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/rubygems.org/gems/swistaczek-localtunnel/versions/0.3.2&#039;]);&quot;  href=&quot;https://rubygems.org/gems/swistaczek-localtunnel/versions/0.3.2&quot;&gt;ruby gems&lt;/a&gt; and a go &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/progrium/localtunnel&#039;]);&quot;  href=&quot;https://github.com/progrium/localtunnel&quot;&gt;localtunnel&lt;/a&gt; available to us. And there are the prominent services &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/localtunnel.me/&#039;]);&quot;  href=&quot;http://localtunnel.me/&quot;&gt;localtunnel.me&lt;/a&gt; and &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/ngrok.com/&#039;]);&quot;  href=&quot;https://ngrok.com/&quot;&gt;ngrok.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I shared that on Twitter the other day, I got two responses going different directions. On the &quot;positive&quot; side there was &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/twitter.com/ginader&#039;]);&quot;  href=&quot;https://twitter.com/ginader&quot;&gt;Dirk&lt;/a&gt; being surprised localtunnel was now on npm and explaining how useful the tool is for conferences and demos. The &quot;negative&quot; side was &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/tobiastom.name/&#039;]);&quot;  href=&quot;https://tobiastom.name/&quot;&gt;Tobias&lt;/a&gt;, complaining how &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/twitter.com/tobiastom/status/594952415583051776&#039;]);&quot;  href=&quot;https://twitter.com/tobiastom/status/594952415583051776&quot;&gt;you don&#039;t need any of that&lt;/a&gt;, if you&#039;d only understood SSH. What he neglected to mention is that you also need your own server that you can connect to via SSH.&lt;/p&gt;

&lt;p&gt;Having my own root servers and dot wanting to die dumb I investigated &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.howtoforge.com/reverse-ssh-tunneling&#039;]);&quot;  href=&quot;https://www.howtoforge.com/reverse-ssh-tunneling&quot;&gt;SSH Reverse Tunneling&lt;/a&gt; and with a bit of help from &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/twitter.com/cjk101010&#039;]);&quot;  href=&quot;https://twitter.com/cjk101010&quot;&gt;Christian&lt;/a&gt; finally figured out what I needed to do.&lt;/p&gt;

&lt;h2&gt;Configuring sshd&lt;/h2&gt;

&lt;p&gt;Let&#039;s first check if we even need to configure anything at all. Connect to your server (&lt;code&gt;$server&lt;/code&gt;) and with privileges (&lt;code&gt;su&lt;/code&gt; or &lt;code&gt;sudo&lt;/code&gt;) run the following command:&lt;/p&gt;

&lt;div class=&quot;bash geshi&quot; style=&quot;text-align: left&quot;&gt;sshd &lt;span style=&quot;color: #660033;&quot;&gt;-T&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;grep&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-E&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&#039;gatewayports|allowtcpforwarding&#039;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;the output looks like this (with &lt;code&gt;yes&lt;/code&gt; and &lt;code&gt;no&lt;/code&gt; depending on your current configuration):&lt;/p&gt;

&lt;div class=&quot;plain geshi&quot; style=&quot;text-align: left&quot;&gt;gatewayports no&lt;br /&gt;
allowtcpforwarding yes&lt;/div&gt;

&lt;p&gt;We need to make sure both values are set to &lt;code&gt;yes&lt;/code&gt; in the sshf config file - usually located at &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;, or &lt;code&gt;/etc/sshd_config&lt;/code&gt; if you&#039;re on a Mac.&lt;/p&gt;

&lt;h3&gt;User-Specific sshd Configuration&lt;/h3&gt;

&lt;p&gt;You can limit the privilege of port forwarding to your own user by using a &lt;code&gt;Match User&lt;/code&gt; statement:&lt;/p&gt;

&lt;div class=&quot;plain geshi&quot; style=&quot;text-align: left&quot;&gt;# allow reverse tunneling only to the user rrehm&lt;br /&gt;
Match User rrehm&lt;br /&gt;
&amp;#160; AllowTcpForwarding yes&lt;br /&gt;
&amp;#160; GatewayPorts yes&lt;/div&gt;

&lt;p&gt;To verify the configuration specific to your user, run the following command providing your username and port to bind. The other options don&#039;t really matter, unless you&#039;ve added more limitations to &lt;code&gt;Match&lt;/code&gt; (see &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/raymii.org/s/tutorials/Limit_access_to_openssh_features_with_the_Match_keyword.html&#039;]);&quot;  href=&quot;https://raymii.org/s/tutorials/Limit_access_to_openssh_features_with_the_Match_keyword.html&quot;&gt;Limit access to openssh features with the Match option&lt;/a&gt; for inspiration).&lt;/p&gt;

&lt;div class=&quot;bash geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #007800;&quot;&gt;user&lt;/span&gt;=rrehm&lt;br /&gt;&lt;span style=&quot;color: #007800;&quot;&gt;port&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;12345&lt;/span&gt;&lt;br /&gt;sshd &lt;span style=&quot;color: #660033;&quot;&gt;-T&lt;/span&gt; \&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #660033;&quot;&gt;-C&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;user&lt;/span&gt;=&lt;span style=&quot;color: #800000;&quot;&gt;${user}&lt;/span&gt; \&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #660033;&quot;&gt;-C&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;host&lt;/span&gt;=&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;*&lt;/span&gt; \&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #660033;&quot;&gt;-C&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;addr&lt;/span&gt;=&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;*&lt;/span&gt; \&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #660033;&quot;&gt;-C&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;laddr&lt;/span&gt;=&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;*&lt;/span&gt; \&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #660033;&quot;&gt;-C&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;lport&lt;/span&gt;=&lt;span style=&quot;color: #800000;&quot;&gt;${port}&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;grep&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-E&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&#039;gatewayports|allowtcpforwarding&#039;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;again, this should output&lt;/p&gt;

&lt;div class=&quot;plain geshi&quot; style=&quot;text-align: left&quot;&gt;gatewayports yes&lt;br /&gt;
allowtcpforwarding yes&lt;/div&gt;

&lt;h2&gt;Opening SSH Reverse Tunnels&lt;/h2&gt;

&lt;p&gt;With sshd configured, all we need to do is tell &lt;code&gt;ssh&lt;/code&gt; which port we want mapped:&lt;/p&gt;

&lt;div class=&quot;bash geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #007800;&quot;&gt;user&lt;/span&gt;=rrehm&lt;br /&gt;&lt;span style=&quot;color: #007800;&quot;&gt;server&lt;/span&gt;=example.org&lt;br /&gt;&lt;span style=&quot;color: #007800;&quot;&gt;remotePort&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;1234&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #007800;&quot;&gt;localPort&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;80&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;ssh&lt;/span&gt; &lt;span style=&quot;color: #800000;&quot;&gt;${user}&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;${server}&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-R&lt;/span&gt; &lt;span style=&quot;color: #800000;&quot;&gt;${remotePort}&lt;/span&gt;:localhost:&lt;span style=&quot;color: #800000;&quot;&gt;${localPort}&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;If you only want to bind the ports but not actually have a shell opened, add &lt;code&gt;-N&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;bash geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;ssh&lt;/span&gt; &lt;span style=&quot;color: #800000;&quot;&gt;${user}&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;${server}&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-N&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-R&lt;/span&gt; &lt;span style=&quot;color: #800000;&quot;&gt;${remotePort}&lt;/span&gt;:localhost:&lt;span style=&quot;color: #800000;&quot;&gt;${localPort}&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;when you&#039;re done, &lt;kbd&gt;Control C&lt;/kbd&gt; will terminate the SSH connection and your local server will no longer be available remotely.&lt;/p&gt;

&lt;h3&gt;Making SSH Reverse Tunnels Reconnect Automatically&lt;/h3&gt;

&lt;p&gt;If you want your tunnel(s) to automatically reconnect (when switching WiFis, for example), have a look at &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.harding.motd.ca/autossh/&#039;]);&quot;  href=&quot;http://www.harding.motd.ca/autossh/&quot;&gt;autossh&lt;/a&gt; (available via &lt;code&gt;brew install autossh&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;bash geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;#!/bin/bash&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;# it&#039;s usually a good idea to exit upon error&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;set&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-e&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;# your connection parameters&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #007800;&quot;&gt;user&lt;/span&gt;=rrehm&lt;br /&gt;&lt;span style=&quot;color: #007800;&quot;&gt;server&lt;/span&gt;=example.org&lt;br /&gt;&lt;span style=&quot;color: #007800;&quot;&gt;remotePort&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;1234&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #007800;&quot;&gt;localPort&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;80&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;# some stuff autossh needs to know&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #007800;&quot;&gt;AUTOSSH_SERVER_ALIVE_INTERVAL&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;30&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #007800;&quot;&gt;AUTOSSH_SERVER_ALIVE_COUNT&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;2&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;AUTOSSH_POLL&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;30&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;AUTOSSH_GATETIME&lt;/span&gt;=&lt;span style=&quot;color: #000000;&quot;&gt;0&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #007800;&quot;&gt;AUTOSSH_LOGFILE&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;/tmp/autossh.log&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;# clean up log file on start&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;touch&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&lt;span style=&quot;color: #007800;&quot;&gt;${AUTOSSH_LOGFILE}&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;rm&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&lt;span style=&quot;color: #007800;&quot;&gt;${AUTOSSH_LOGFILE}&lt;/span&gt;&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;||&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;true&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;autossh &lt;span style=&quot;color: #660033;&quot;&gt;-f&lt;/span&gt; &lt;span style=&quot;color: #660033;&quot;&gt;-M&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;0&lt;/span&gt; \&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #660033;&quot;&gt;-o&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;ExitOnForwardFailure yes&amp;quot;&lt;/span&gt; \&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #660033;&quot;&gt;-o&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;ServerAliveInterval &lt;span style=&quot;color: #007800;&quot;&gt;${AUTOSSH_SERVER_ALIVE_INTERVAL}&lt;/span&gt;&amp;quot;&lt;/span&gt; \&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #660033;&quot;&gt;-o&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;ServerAliveCountMax &lt;span style=&quot;color: #007800;&quot;&gt;${AUTOSSH_SERVER_ALIVE_COUNT}&lt;/span&gt;&amp;quot;&lt;/span&gt; \&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #660033;&quot;&gt;-A&lt;/span&gt; &lt;span style=&quot;color: #800000;&quot;&gt;${user}&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;@&lt;/span&gt;&lt;span style=&quot;color: #800000;&quot;&gt;${server}&lt;/span&gt; \&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #660033;&quot;&gt;-R&lt;/span&gt; &lt;span style=&quot;color: #800000;&quot;&gt;${remotePort}&lt;/span&gt;:localhost:&lt;span style=&quot;color: #800000;&quot;&gt;${localPort}&lt;/span&gt;&lt;/div&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;You can expose local services on your remote servers, given you have a server you can SSH to. Using &lt;code&gt;autossh&lt;/code&gt; the tunnel can be re-established automatically when it collapses. While this solves &lt;em&gt;most&lt;/em&gt; of my personal problems, it is still inferior to &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/ngrok.com/&#039;]);&quot;  href=&quot;https://ngrok.com/&quot;&gt;ngrok&lt;/a&gt;. The vanilla SSH approach knows nothing about the protocols in use. It simply forwards a port, regardless of the service (HTTP, MySQL, SMTP, …). With a simple &lt;code&gt;ngrok http 8080&lt;/code&gt; you&#039;ll have remote access to your local webserver through HTTP and HTTPS - even if your local webserver only sports HTTP.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Thu, 28 May 2015 01:09:20 +0200</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/38-guid.html</guid>
    
</item>
<item>
    <title>Starting CLI Services In Sequence</title>
    <link>https://blog.rodneyrehm.de/archives/37-Starting-CLI-Services-In-Sequence.html</link>
            <category>shell</category>
    
    <comments>https://blog.rodneyrehm.de/archives/37-Starting-CLI-Services-In-Sequence.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=37</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=37</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;Running a couple of scripts in a row is no problem for Bash, but running them in parallel is more tricky. It gets even more ridiculous when on script needs to reach a certain state before another can start. This post illustrates how I solved this work using AppleScript. ## The Problem ## {#problem}&lt;/p&gt;

&lt;p&gt;Before we get to the solution, let&#039;s look at the problem first. The concrete task at hand (rather sequence thereof) looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;open an SSH tunnel, let&#039;s call it Fred&lt;/li&gt;
&lt;li&gt;open an SSH tunnel through Fred, let&#039;s call it Bob&lt;/li&gt;
&lt;li&gt;download a couple of things through Bob&lt;/li&gt;
&lt;li&gt;start a service that logs to the TTY&lt;/li&gt;
&lt;li&gt;invoke a client that does something with the service,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every task is dependent upon the one previous to it. It&#039;s a classic, linear dependency chain. Were these tasks finite, a bash script could look as simple as&lt;/p&gt;

&lt;div class=&quot;bash geshi&quot; style=&quot;text-align: left&quot;&gt;.&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;call-fred.sh&lt;br /&gt;.&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;call-bob.sh&lt;br /&gt;.&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;download-stuff.sh&lt;br /&gt;.&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;start-server.sh&lt;br /&gt;.&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&lt;/span&gt;run-client.sh&lt;/div&gt;

&lt;p&gt;But since, with the exception of &lt;code&gt;download-stuff&lt;/code&gt; and &lt;code&gt;run-client&lt;/code&gt;, everything is a service, the processes never end, so the next line of the bash file would never be invoked. You could &quot;daemonize&quot; the tasks, so they run in the background. But in the case of &lt;code&gt;call-bob&lt;/code&gt; (where I get a remote shell) and &lt;code&gt;start-server&lt;/code&gt; (where I get a local console) daemonizing wouldn&#039;t do much good.&lt;/p&gt;

&lt;h2 id=&quot;applescript&quot;&gt;Meet AppleScript&lt;/h2&gt;

&lt;p&gt;Luckily Apple has automation features built into OSX. For applications that expose themselves to this API all sorts of &quot;funky&quot; things are made possible. For iTerm this means that we can control the windows themselves, throw keyboard events at the terminal windows and more. They are scriptable through &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/developer.apple.com/library/mac/documentation/applescript/Conceptual/AppleScriptX/AppleScriptX.html&#039;]);&quot;  href=&quot;https://developer.apple.com/library/mac/documentation/applescript/Conceptual/AppleScriptX/AppleScriptX.html&quot;&gt;AppleScript&lt;/a&gt; - a language that does not only sound wrong, but looks like it was designed for three year olds. Have a look at this &lt;code&gt;example.applescript&lt;/code&gt; for the basic boilerplate.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NOTE&lt;/em&gt; the &lt;code&gt;¬&lt;/code&gt; character is the &quot;ignore this line-break&quot; escape like &lt;code&gt;\&lt;/code&gt; is in bash.&lt;/p&gt;

&lt;div class=&quot;applescript geshi&quot; style=&quot;text-align: left&quot;&gt;#!&lt;span style=&quot;color: #66cc66;&quot;&gt;/&lt;/span&gt;usr&lt;span style=&quot;color: #66cc66;&quot;&gt;/&lt;/span&gt;bin&lt;span style=&quot;color: #66cc66;&quot;&gt;/&lt;/span&gt;osascript&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; application &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;iTerm&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; current terminal&lt;br /&gt;&amp;#160; &amp;#160; activate current session&lt;br /&gt;&amp;#160; &amp;#160; &lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;-- required to leave the session occupied by osascript&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; application &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;System Events&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;to&lt;/span&gt; keystroke &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;d&amp;quot;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; using &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#123;&lt;/span&gt;command down, shift down&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; delay &lt;span style=&quot;color: #cc66cc;&quot;&gt;0.5&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;last&lt;/span&gt; session&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;-- run `echo &#039;Hello World&#039;`&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; write text &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;echo &#039;Hello World&#039;&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;-- can be repeated as often as you want&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; application &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;System Events&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;to&lt;/span&gt; keystroke &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;d&amp;quot;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; using &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#123;&lt;/span&gt;command down, shift down&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; delay &lt;span style=&quot;color: #cc66cc;&quot;&gt;0.5&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;last&lt;/span&gt; session&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; write text &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;echo &#039;Oh look, a Split Pane!&#039;&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;What this example doesn&#039;t show is that opening the third split pane will not wait for the first &lt;code&gt;echo&lt;/code&gt; to finish. This is happening in parallel. But since we need to make sure that the preceding task is in a certain state, we can use the following snippet to block until we&#039;re certain we can continue:&lt;/p&gt;

&lt;div class=&quot;applescript geshi&quot; style=&quot;text-align: left&quot;&gt;#!&lt;span style=&quot;color: #66cc66;&quot;&gt;/&lt;/span&gt;usr&lt;span style=&quot;color: #66cc66;&quot;&gt;/&lt;/span&gt;bin&lt;span style=&quot;color: #66cc66;&quot;&gt;/&lt;/span&gt;osascript&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; application &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;iTerm&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; current terminal&lt;br /&gt;&amp;#160; &amp;#160; activate current session&lt;br /&gt;&amp;#160; &amp;#160; &lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;-- required to leave the session occupied by osascript&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; application &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;System Events&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;to&lt;/span&gt; keystroke &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;d&amp;quot;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; using &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#123;&lt;/span&gt;command down, shift down&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; delay &lt;span style=&quot;color: #cc66cc;&quot;&gt;0.5&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;last&lt;/span&gt; session&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;-- run `./call-fred.sh`&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; write text &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;/bin/bash /path/to/call-fred.sh&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;repeat&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;while&lt;/span&gt; contents does &lt;span style=&quot;color: #000066;&quot;&gt;not&lt;/span&gt; contain ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;fred is ready for business&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; delay &lt;span style=&quot;color: #cc66cc;&quot;&gt;0.01&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;repeat&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;-- won&#039;t reach this line before &amp;quot;fred is ready for business&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;-- was printed to the terminal&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.mactech.com/articles/mactech/Vol.20/20.12/RepeatLoops/index.html&#039;]);&quot;  href=&quot;http://www.mactech.com/articles/mactech/Vol.20/20.12/RepeatLoops/index.html&quot;&gt;Should I Repeat Myself?&lt;/a&gt; has some more example loops. That doesn&#039;t look very sexy, but it gets the job done. To make the thing a bit more readable, we can introduce functions:&lt;/p&gt;

&lt;div class=&quot;applescript geshi&quot; style=&quot;text-align: left&quot;&gt;#!&lt;span style=&quot;color: #66cc66;&quot;&gt;/&lt;/span&gt;usr&lt;span style=&quot;color: #66cc66;&quot;&gt;/&lt;/span&gt;bin&lt;span style=&quot;color: #66cc66;&quot;&gt;/&lt;/span&gt;osascript&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; application &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;iTerm&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; current terminal&lt;br /&gt;&amp;#160; &amp;#160; activate current session&lt;br /&gt;&amp;#160; &amp;#160; &lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;-- required to leave the session occupied by osascript&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;my&lt;/span&gt; addSplitPane&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;my&lt;/span&gt; runAndWait&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;/bin/bash /path/to/call-fred.sh&amp;quot;&lt;/span&gt;, ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;fred is ready for business&amp;quot;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;on&lt;/span&gt; addSplitPane&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; application &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;iTerm&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; current terminal&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; activate&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; application &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;System Events&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;to&lt;/span&gt; keystroke &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;d&amp;quot;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; using &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#123;&lt;/span&gt;command down, shift down&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; delay &lt;span style=&quot;color: #cc66cc;&quot;&gt;0.5&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; addSplitPane&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;on&lt;/span&gt; runAndWait&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;command, response&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; application &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;iTerm&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; current terminal&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; activate&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;last&lt;/span&gt; session&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; write text command&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;repeat&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;while&lt;/span&gt; contents does &lt;span style=&quot;color: #000066;&quot;&gt;not&lt;/span&gt; contain response&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; delay &lt;span style=&quot;color: #cc66cc;&quot;&gt;0.01&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;repeat&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; runAndWait&lt;/div&gt;

&lt;p&gt;I had hoped that you could save a session to a variable and replace the &lt;code&gt;tell the last session&lt;/code&gt; with &lt;code&gt;tell mySessionThing&lt;/code&gt; to interleave concurrent tasks. Well, you can, but a session refers to something that is &lt;em&gt;not&lt;/em&gt; the split pane. To cover that I&#039;d have had to send keyboard commands to navigate the split panes - making it necessary to know which one your in. That sounded like a very dumb idea, so I dropped the little optimization and ended up with simply opening new sessions instead:&lt;/p&gt;

&lt;div class=&quot;applescript geshi&quot; style=&quot;text-align: left&quot;&gt;#!&lt;span style=&quot;color: #66cc66;&quot;&gt;/&lt;/span&gt;usr&lt;span style=&quot;color: #66cc66;&quot;&gt;/&lt;/span&gt;bin&lt;span style=&quot;color: #66cc66;&quot;&gt;/&lt;/span&gt;osascript&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; application &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;iTerm&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; current terminal&lt;br /&gt;&amp;#160; &amp;#160; activate current session&lt;br /&gt;&amp;#160; &amp;#160; &lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;-- open SSH tunnels&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;my&lt;/span&gt; addSplitPane&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;my&lt;/span&gt; runAndWait&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;/bin/bash /path/to/call-fred.sh&amp;quot;&lt;/span&gt;, ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;fred is ready for business&amp;quot;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;my&lt;/span&gt; addSplitPane&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;my&lt;/span&gt; runAndWait&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;/bin/bash /path/to/call-bob.sh&amp;quot;&lt;/span&gt;, ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;bob here, hello?&amp;quot;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;-- update code base&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #000066;&quot;&gt;launch&lt;/span&gt; session &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;Default&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; delay &lt;span style=&quot;color: #cc66cc;&quot;&gt;0.5&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;last&lt;/span&gt; session&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; write text &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;/bin/bash /path/to/update.sh&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;-- start server (in parallel to code base update)&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #000066;&quot;&gt;launch&lt;/span&gt; session &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;Default&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; delay &lt;span style=&quot;color: #cc66cc;&quot;&gt;0.5&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;my&lt;/span&gt; runAndWait&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;/bin/bash /path/to/update-server.sh&amp;quot;&lt;/span&gt;, ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;[INFO] BUILD SUCCESS&amp;quot;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;my&lt;/span&gt; runAndWait&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;/bin/bash /path/to/start-server.sh&amp;quot;&lt;/span&gt;, ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;State Change from INITIALIZING to ACTIVE&amp;quot;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;-- do something with server&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #000066;&quot;&gt;launch&lt;/span&gt; session &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;Default&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; delay &lt;span style=&quot;color: #cc66cc;&quot;&gt;0.5&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;last&lt;/span&gt; session&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; write text &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;/bin/bash /path/to/client.sh&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;on&lt;/span&gt; addSplitPane&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; application &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;iTerm&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; current terminal&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; activate&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; application &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;System Events&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;to&lt;/span&gt; keystroke &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;d&amp;quot;&lt;/span&gt; ¬&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; using &lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#123;&lt;/span&gt;command down, shift down&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; delay &lt;span style=&quot;color: #cc66cc;&quot;&gt;0.5&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; addSplitPane&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;on&lt;/span&gt; runAndWait&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#40;&lt;/span&gt;command, response&lt;span style=&quot;color: #66cc66;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; application &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;iTerm&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; current terminal&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; activate&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;the&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;last&lt;/span&gt; session&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; write text command&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;repeat&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;while&lt;/span&gt; contents does &lt;span style=&quot;color: #000066;&quot;&gt;not&lt;/span&gt; contain response&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; delay &lt;span style=&quot;color: #cc66cc;&quot;&gt;0.01&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;repeat&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; &lt;span style=&quot;color: #b1b100;&quot;&gt;tell&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #b1b100;&quot;&gt;end&lt;/span&gt; runAndWait&lt;/div&gt;

&lt;p&gt;And run the thing with &lt;code&gt;osascript the-file.applescript &amp;amp;&amp;amp; exit&lt;/code&gt;. The exit part is required for the (successfully) finished script runner to go away. Only if there was an error, would the output of &lt;code&gt;osascript&lt;/code&gt; remain visible.&lt;/p&gt;

&lt;p&gt;This may not seem like much, but in this particular case I simply boot my machine and 10 minutes later have an up-to-date and fully initialized system to work with. I&#039;m looking forward to a new morning routine :)&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Tue, 10 Jun 2014 18:08:08 +0200</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/37-guid.html</guid>
    
</item>
<item>
    <title>Always Run Script As Root</title>
    <link>https://blog.rodneyrehm.de/archives/36-Always-Run-Script-As-Root.html</link>
            <category>shell</category>
    
    <comments>https://blog.rodneyrehm.de/archives/36-Always-Run-Script-As-Root.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=36</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=36</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;Shell scripts (often referred to bash scripting, even though it&#039;s not necessarily bash) are a great way to automate certain things. Every now and then those scripts have to be run with privileges - in order to, say, register a network interface alias or bind a low-port.&lt;/p&gt;

&lt;p&gt;## Force Root  ## {#force-root}&lt;/p&gt;

&lt;div class=&quot;bash geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #666666; font-style: italic;&quot;&gt;# ensure running as root&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;&amp;#91;&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;&lt;span style=&quot;color: #007800;&quot;&gt;$(id -u)&lt;/span&gt;&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;!&lt;/span&gt;= &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;&amp;#93;&lt;/span&gt;; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;then&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #7a0874; font-weight: bold;&quot;&gt;exec&lt;/span&gt; &lt;span style=&quot;color: #c20cb9; font-weight: bold;&quot;&gt;sudo&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;$0&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;$@&amp;quot;&lt;/span&gt; &lt;br /&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;fi&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;This allows me to call a script either with &lt;code&gt;sudo ./the-script.sh&lt;/code&gt; or simply &lt;code&gt;./the-script.sh&lt;/code&gt; and thus not have to add &lt;code&gt;sudo&lt;/code&gt; in front of all commands within the script.&lt;/p&gt;

&lt;h2 id=&quot;automatic-root&quot;&gt;Automatic Root&lt;/h2&gt;

&lt;p&gt;If you want to get rid of having to enter a password for a specific script, sudoers is your friend:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;open terminal&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;visudo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;move down to the end of the file&lt;/li&gt;
&lt;li&gt;press &lt;code&gt;i&lt;/code&gt; (for &quot;insert&quot;)&lt;/li&gt;
&lt;li&gt;add &lt;code&gt;username host = (root) NOPASSWD: command&lt;/code&gt; (which can be &lt;code&gt;rrehm ALL = (root) NOPASSWD: /usr/local/bin/the-script.sh&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;press &lt;code&gt;ESC&lt;/code&gt; (escape)&lt;/li&gt;
&lt;li&gt;press &lt;code&gt;:&lt;/code&gt; (colon to enter command mode)&lt;/li&gt;
&lt;li&gt;write &lt;code&gt;wq&lt;/code&gt; (for &quot;write quit&quot;)&lt;/li&gt;
&lt;li&gt;press enter&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since you won&#039;t have to enter your root password anymore when running the-script.sh, you want to make sure that only root can edit the file so nobody can abuse this script to run arbitrary commands as root:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;open terminal&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;sudo chown root:wheel /usr/local/bin/the-script.sh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;sudo chmod u+rwx /usr/local/bin/the-script.sh&lt;/code&gt; (to allow root reading, writing and executing)&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;sudo chmod go-w+rx /usr/local/bin/the-script.sh&lt;/code&gt; (to allow everyone to execute and read, but writing)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;and that&#039;s it, run &lt;code&gt;the-script.sh&lt;/code&gt; in the terminal, as root, without having to enter a password.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Fri, 06 Jun 2014 14:42:54 +0200</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/36-guid.html</guid>
    
</item>
<item>
    <title>Including Data From Github</title>
    <link>https://blog.rodneyrehm.de/archives/35-Including-Data-From-Github.html</link>
    
    <comments>https://blog.rodneyrehm.de/archives/35-Including-Data-From-Github.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=35</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=35</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;We use services like &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/jsbin.com/&#039;]);&quot;  href=&quot;http://jsbin.com/&quot;&gt;JSBin&lt;/a&gt;, &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/jsfiddle.net/&#039;]);&quot;  href=&quot;http://jsfiddle.net/&quot;&gt;JSFiddle&lt;/a&gt;, &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/dabblet.com/&#039;]);&quot;  href=&quot;http://dabblet.com/&quot;&gt;Dabblet&lt;/a&gt; and &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/codepen.io/&#039;]);&quot;  href=&quot;http://codepen.io/&quot;&gt;Codepen&lt;/a&gt; to quickly make examples and demos available online. We do this to show interactive things on our blogs and to provide a test-case when submitting issues. Some of us even use these services for development. All those services have one problem, though: including JSON files, scripts and resources from Github is not possible out of the box. ---&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL/DR:&lt;/strong&gt; Use &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/rawgithub.com/&#039;]);&quot;  href=&quot;https://rawgithub.com/&quot;&gt;rawgithub.com&lt;/a&gt; and &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.corsproxy.com/&#039;]);&quot;  href=&quot;http://www.corsproxy.com/&quot;&gt;CORS Proxy&lt;/a&gt; to load resources from Github and use them in your fiddles. Read &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/medium.com/the-javascript-collection/9a61872c61cd&#039;]);&quot;  href=&quot;https://medium.com/the-javascript-collection/9a61872c61cd&quot;&gt;The Naughtyness Score&lt;/a&gt; for more information.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;It&#039;s not the services fault that a simple JavaScript file can&#039;t be loaded from a repository on github. Github actively prevents anyone from &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/en.wikipedia.org/wiki/Hotlinking&#039;]);&quot;  href=&quot;http://en.wikipedia.org/wiki/Hotlinking&quot;&gt;hotlinking&lt;/a&gt; resources. And in all fairness, this is a good thing. If Github wasn&#039;t taking steps to prevent traffic abuse, people would simply load all their files from Github servers, rather than using CDNs or their own infrastructures.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;This is important!&lt;/strong&gt; Never abuse the advice given in this article in production systems. Only do this for tinkering and providing demos on one of the fiddle-platforms.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As a library author I&#039;d like to provide fiddles to my libraries so people can play around with things. More importantly I want people to provide test-cases when filing bug reports.&lt;/p&gt;

&lt;p&gt;Say I wanted to show you how &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/medialize.github.com/URI.js/&#039;]);&quot;  href=&quot;http://medialize.github.com/URI.js/&quot;&gt;URI.js&lt;/a&gt; does URI normalization, I&#039;d provide a fiddle with the following content:&lt;/p&gt;

&lt;div class=&quot;xml geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;script&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;src&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;https://raw2.github.com/medialize/URI.js/master/src/URI.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/script&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;script&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; var uri = URI(&#039;hTTp://fOo.example.org:80/some/../directory/./file.html&#039;);&lt;br /&gt;&amp;#160; // output: &amp;quot;http://foo.example.org/directory/file.html&amp;quot;&lt;br /&gt;&amp;#160; alert(uri.normalize());&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/script&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;And that would work in Firefox, but fail in Chrome - try &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/jsbin.com/jogil/1&#039;]);&quot;  href=&quot;http://jsbin.com/jogil/1&quot;&gt;this fiddle&lt;/a&gt; in both browsers.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;prevent-hotlinking&quot;&gt;How Github Is Preventing Hotlinking&lt;/h2&gt;

&lt;p&gt;Before we get into solving the problem, let&#039;s first have a look at what is causing this behavior. We can see the HTTP headers sent by Github by using curl on the command line:&lt;/p&gt;

&lt;div class=&quot;bash geshi&quot; style=&quot;text-align: left&quot;&gt;curl &lt;span style=&quot;color: #660033;&quot;&gt;-I&lt;/span&gt; &lt;span style=&quot;color: #ff0000;&quot;&gt;&#039;https://raw2.github.com/medialize/URI.js/master/src/URI.js&#039;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;stripping out the noise we&#039;re left with the following &quot;offending&quot; headers:&lt;/p&gt;

&lt;div class=&quot;text geshi&quot; style=&quot;text-align: left&quot;&gt;Content-Type: text/plain; charset=utf-8&lt;br /&gt;Access-Control-Allow-Origin: https://render.github.com&lt;br /&gt;Content-Disposition: inline&lt;br /&gt;X-Content-Type-Options: nosniff&lt;br /&gt;X-Frame-Options: deny&lt;/div&gt;

&lt;h3 id=&quot;prevent-content-type&quot;&gt;&lt;code&gt;Content-Type&lt;/code&gt; and &lt;code&gt;Content-Disposition&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;The first issue is &lt;code&gt;Content-Type: text/plain&lt;/code&gt;. All text resources are sent as plain text, no matter what they really are (&lt;code&gt;text/css&lt;/code&gt;, &lt;code&gt;text/html&lt;/code&gt;, &lt;code&gt;text/javascript&lt;/code&gt;, &lt;code&gt;application/javascript&lt;/code&gt;, &lt;code&gt;application/json&lt;/code&gt;, …). Unless a file is said to be &lt;code&gt;text/html&lt;/code&gt;, a browser won&#039;t render the HTML, but print the text instead. (ignoring mime detection, explained later in this post)&lt;/p&gt;

&lt;p&gt;For binary files, like videos, the proper &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/en.wikipedia.org/wiki/Mime-type&#039;]);&quot;  href=&quot;http://en.wikipedia.org/wiki/Mime-type&quot;&gt;mime-type&lt;/a&gt; is sent, e.g. &lt;code&gt;Content-Type: audio/webm&lt;/code&gt;. But by using the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/tools.ietf.org/html/rfc2616#section-19.5.1&#039;]);&quot;  href=&quot;http://tools.ietf.org/html/rfc2616#section-19.5.1&quot;&gt;&lt;code&gt;Content-Disposition: attachment&lt;/code&gt;&lt;/a&gt; header, Github instructs the browser to show a &lt;em&gt;save to disk&lt;/em&gt; dialog, rather than rendering the content.&lt;/p&gt;

&lt;p&gt;Images (PNG, JPG, GIF) are served in a way that allow out-of-the-box inclusion.&lt;/p&gt;

&lt;h3 id=&quot;prevent-cors&quot;&gt;&lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; - preventing CORS&lt;/h3&gt;

&lt;p&gt;By setting the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.w3.org/TR/cors/#access-control-allow-origin-response-header&#039;]);&quot;  href=&quot;http://www.w3.org/TR/cors/#access-control-allow-origin-response-header&quot;&gt;Access-Control-Allow-Origin&lt;/a&gt; header to &lt;code&gt;https://render.github.com&lt;/code&gt; rather than &lt;code&gt;*&lt;/code&gt; (everyone), Github explicitly forbids loading resources via &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/developer.mozilla.org/de/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest&#039;]);&quot;  href=&quot;https://developer.mozilla.org/de/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest&quot;&gt;XHR&lt;/a&gt; (XMLHTTPRequest - often referred to as AJAX).&lt;/p&gt;

&lt;h3 id=&quot;prevent-content-options&quot;&gt;&lt;code&gt;X-Content-Type-Options&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;By setting the non-standard header &lt;code&gt;X-Content-Type-Options: nosniff&lt;/code&gt; Github instructs browsers (currently Internet Explorer and Google Chrome) to not guess the content type by looking at the content. For compatibility reasons Internet Explorer could determine that the content is HTML and overwrite &lt;code&gt;Content-Type: text/plain&lt;/code&gt; to &lt;code&gt;Content-Type: text/html&lt;/code&gt;. More on this in &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/blogs.msdn.com/b/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx&#039;]);&quot;  href=&quot;http://blogs.msdn.com/b/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx&quot;&gt;IE8 Security Part V: Comprehensive Protection&lt;/a&gt; (scroll down to MIME-Handling Changes).&lt;/p&gt;

&lt;h3 id=&quot;prevent-frames&quot;&gt;&lt;code&gt;X-Frame-Options&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;By setting &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options&#039;]);&quot;  href=&quot;https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options&quot;&gt;&lt;code&gt;X-Frame-Options: deny&lt;/code&gt;&lt;/a&gt; Github forbids browsers to embed that content in an iFrame.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;use-proxy&quot;&gt;Using A Proxy To Circumvent Hotlink-Prevention&lt;/h2&gt;

&lt;p&gt;Now that we know why our browser&#039;s won&#039;t let us include raw Github resources, it&#039;s time to introduce &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/rawgithub.com&#039;]);&quot;  href=&quot;http://rawgithub.com&quot;&gt;rawgithub.com&lt;/a&gt;. It&#039;s a proxy service stripping Github&#039;s &quot;offending&quot; HTTP headers and adding a proper content type. By replacing your original URL &lt;code&gt;https://raw.github.com/name/repo/…&lt;/code&gt; with &lt;code&gt;https://rawgithub.com/name/repo/…&lt;/code&gt; (notice we only removed the &lt;code&gt;.&lt;/code&gt; from &lt;code&gt;raw.github&lt;/code&gt;) you&#039;re ready to go. The service&#039;s source is available at &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/rgrove/rawgithub&#039;]);&quot;  href=&quot;https://github.com/rgrove/rawgithub&quot;&gt;rgrove/rawgithub.com&lt;/a&gt;, should you want to run the proxy service yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caveat:&lt;/strong&gt; rawgithub.com won&#039;t proxy binary files. Images and videos are forwarded (&lt;code&gt;301 Moved Permanently&lt;/code&gt;) to the original location on Github. For images this works well, for videos it won&#039;t.&lt;/p&gt;

&lt;p&gt;Because rawgithub.com also adds a wildcard CORS header (&lt;code&gt;Access-Control-Allow-Origin: *&lt;/code&gt;), you can access all your data with XMLHttpRequest.&lt;/p&gt;

&lt;p&gt;You may also want to load data off another domain than just your Github repositories. For use with XMLHttpRequest the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.corsproxy.com/&#039;]);&quot;  href=&quot;http://www.corsproxy.com/&quot;&gt;corsproxy.com&lt;/a&gt; can ease your pain. Be aware that corsproxy does not work on Github&#039;s content.&lt;/p&gt;

&lt;h2 id=&quot;rawgithub-gist&quot;&gt;Using rawgithub.com for a gist&lt;/h2&gt;

&lt;p&gt;On the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/rawgithub.com&#039;]);&quot;  href=&quot;http://rawgithub.com&quot;&gt;rawgithub.com&lt;/a&gt; website they claim support for &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/gist.github.com&#039;]);&quot;  href=&quot;https://gist.github.com&quot;&gt;gist.github.com&lt;/a&gt; - and it works, but with a small caveat.&lt;/p&gt;

&lt;p&gt;When you create a gist, you don&#039;t know its URL beforehand. The raw URLs of files within a gist aren&#039;t guessable, as they contain a hash that is unique to each file and revision. I&#039;m not sure where this hash comes from, but it&#039;s got nothing to do with the git commit.&lt;/p&gt;

&lt;p&gt;Anyway, you can create a gist containing multiple files (&lt;code&gt;index.html&lt;/code&gt;, &lt;code&gt;style.css&lt;/code&gt;, &lt;code&gt;script.js&lt;/code&gt;) like I did in this &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/gist.github.com/rodneyrehm/9020346&#039;]);&quot;  href=&quot;https://gist.github.com/rodneyrehm/9020346&quot;&gt;this demo gist&lt;/a&gt;. Within the &lt;code&gt;index.html&lt;/code&gt; you&#039;re likely to include &lt;code&gt;style.css&lt;/code&gt; and &lt;code&gt;script.js&lt;/code&gt; as relative resources. When asking the gist.github.com UI for the raw view of &lt;code&gt;index.html&lt;/code&gt;, you&#039;re pointed to &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/gist.github.com/rodneyrehm/9020346/raw/9a835b17cd45b3ac2c0c91d7e5fd146ef32c65f3/index.html&#039;]);&quot;  href=&quot;https://gist.github.com/rodneyrehm/9020346/raw/9a835b17cd45b3ac2c0c91d7e5fd146ef32c65f3/index.html&quot;&gt;&lt;code&gt;rodneyrehm/9020346/raw/9a835b17cd45b3ac2c0c91d7e5fd146ef32c65f3/index.html&lt;/code&gt;&lt;/a&gt;. One might assume changing the filename from &lt;code&gt;index.html&lt;/code&gt; to &lt;code&gt;script.js&lt;/code&gt; would show that file, but it doesn&#039;t, it still shows the content of &lt;code&gt;index.html&lt;/code&gt;. So file identification is performed through the hash (&lt;code&gt;9a835b17cd45b3ac2c0c91d7e5fd146ef32c65f3&lt;/code&gt;) rather than the file (&lt;code&gt;index.html&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The next logical step would be to identify the proper raw URLs for &lt;code&gt;style.css&lt;/code&gt; and &lt;code&gt;script.js&lt;/code&gt; and change their inclusions within &lt;code&gt;index.html&lt;/code&gt; accordingly. But it turns out this really isn&#039;t necessary. Removing the hash from the raw URL gives you the resource at the HEAD commit (i.e. the most recent version): &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/gist.github.com/rodneyrehm/9020346/raw/index.html&#039;]);&quot;  href=&quot;https://gist.github.com/rodneyrehm/9020346/raw/index.html&quot;&gt;&lt;code&gt;rodneyrehm/9020346/raw/index.html&lt;/code&gt;&lt;/a&gt;. Change &lt;code&gt;index.html&lt;/code&gt; to &lt;code&gt;script.js&lt;/code&gt; and you&#039;ll actually see the script&#039;s content.&lt;/p&gt;

&lt;p&gt;Now that relative URLs can be resolved properly, it&#039;s time to replace &lt;code&gt;gist.github.com&lt;/code&gt; by &lt;code&gt;rawgithub.com&lt;/code&gt; and view our gist properly rendered by the browers: &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/rawgithub.com/rodneyrehm/9020346/raw/index.html&#039;]);&quot;  href=&quot;https://rawgithub.com/rodneyrehm/9020346/raw/index.html&quot;&gt;https://rawgithub.com/rodneyrehm/9020346/raw/index.html&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;There are ways around the Same Origin Policy and Github&#039;s foreign resource inclusion restrictions. Make use of them when tinkering with libraries hosted on github. Make use of them, when providing example fiddles. &lt;em&gt;Never use this in production environment&lt;/em&gt; - See &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/medium.com/the-javascript-collection/9a61872c61cd&#039;]);&quot;  href=&quot;https://medium.com/the-javascript-collection/9a61872c61cd&quot;&gt;The Naughtyness Score&lt;/a&gt; for more information.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sun, 16 Feb 2014 13:31:56 +0100</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/35-guid.html</guid>
    
</item>
<item>
    <title>iOS7 - Mobile Safari And Viewport Units</title>
    <link>https://blog.rodneyrehm.de/archives/34-iOS7-Mobile-Safari-And-Viewport-Units.html</link>
            <category>javascript</category>
    
    <comments>https://blog.rodneyrehm.de/archives/34-iOS7-Mobile-Safari-And-Viewport-Units.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=34</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=34</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;The other day I decided it was time to start using viewport relative units - for example &lt;code&gt;height: 100vh;&lt;/code&gt;. According to &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/caniuse.com/#feat=viewport-units&#039;]);&quot;  href=&quot;http://caniuse.com/#feat=viewport-units&quot;&gt;caniuse&lt;/a&gt; my all of &quot;targeted browsers&quot; should&#039;ve worked fine. While The usual suspects - Android Stock Browser and Internet Explorer - behaved formidably, iOS 7 did not. ---&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; There&#039;s a &quot;fix&quot; for the viewport troubles on iOS: &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/rodneyrehm/viewport-units-buggyfill&#039;]);&quot;  href=&quot;https://github.com/rodneyrehm/viewport-units-buggyfill&quot;&gt;viewport-units-buggyfill&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you haven&#039;t heard of viewport units, read &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/dev.opera.com/articles/view/css-viewport-units/&#039;]);&quot;  href=&quot;http://dev.opera.com/articles/view/css-viewport-units/&quot;&gt;CSS viewport units: vw, vh, vmin and vmax&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;identify-problem&quot;&gt;Identifying The Problem&lt;/h2&gt;

&lt;p&gt;What&#039;s the first thing you do when you hit a WTF-moment in development? Exactly, you take a step back and build a minimal test case. You find the smallest amount of code that still reproduces your problem to nail things down. For this particular problem, my &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/jsbin.com/EkorUJI/1/&#039;]);&quot;  href=&quot;http://jsbin.com/EkorUJI/1/&quot;&gt;first test case&lt;/a&gt; looked like this:&lt;/p&gt;

&lt;div class=&quot;xml geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;html&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;head&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;charset&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;title&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;viewport tester&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/title&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;name&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;viewport&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;content&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;width=device-width,initial-scale=1.0&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;style&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; * { margin: 0; padding: 0; }&lt;br /&gt;&amp;#160; &amp;#160; #tester { height: 100vh; }&lt;br /&gt;&amp;#160; &amp;#160; #spacer { height: 3000px }&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/style&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/head&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;body&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;spacer&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/div&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tester&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/div&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;script&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; var windowHeight = window.innerHeight;&lt;br /&gt;&amp;#160; &amp;#160; var bodyHeight = document.body.offsetHeight;&lt;br /&gt;&amp;#160; &amp;#160; var tester = document.getElementById(&#039;tester&#039;);&lt;br /&gt;&amp;#160; &amp;#160; var testerHeight = tester.offsetHeight;&lt;br /&gt;&amp;#160; &amp;#160; console.log(windowHeight, bodyHeight, testerHeight);&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/script&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/body&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;Much to my surprise the numbers were ok. The &lt;code&gt;tester&lt;/code&gt; element actually had the height I expected it would have (exactly that of &lt;code&gt;window.innerHeight&lt;/code&gt;). It took me a while to realize that I had been &lt;em&gt;adding things to the DOM dynamically&lt;/em&gt;. So I &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/jsbin.com/EkorUJI/2/&#039;]);&quot;  href=&quot;http://jsbin.com/EkorUJI/2/&quot;&gt;extended the the test&lt;/a&gt; by a simple function:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;setTimeout&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; el &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; document.&lt;span style=&quot;color: #660066;&quot;&gt;createElement&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;div&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; el.&lt;span style=&quot;color: #660066;&quot;&gt;style&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;height&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;100vh&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; document.&lt;span style=&quot;color: #660066;&quot;&gt;body&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;appendChild&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;el&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #CC0000;&quot;&gt;1000&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;Now the output looked more like what I was seeing in my app. &lt;code&gt;7303, 11606, 4303&lt;/code&gt; On twitter I got pointed to &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/scottjehl/Device-Bugs/issues/36&#039;]);&quot;  href=&quot;https://github.com/scottjehl/Device-Bugs/issues/36&quot;&gt;iOS 6-7 handles viewport relative units really weird&lt;/a&gt; - a 7 month old issue describing what I was seeing on my test devices. According to that issue the problem already existed in iOS6, but my test devices disagreed - everything worked fine.&lt;/p&gt;

&lt;h2 id=&quot;workaround-problem&quot;&gt;Working Around The Problem&lt;/h2&gt;

&lt;p&gt;You&#039;re probably familiar with the term &lt;em&gt;deadline&lt;/em&gt;. I was on one. A colleague had already tried fixing this for 2 days and we had to present this thing the next day. A quick fix - a workaround - was all we were looking for at this point. We were in a lucky spot. Only two selectors were using the &lt;code&gt;vh&lt;/code&gt; unit. The offending selectors only came into play when a certain view was rendered. Replacing the &lt;code&gt;vh&lt;/code&gt; values with &lt;code&gt;px&lt;/code&gt; values seemed crude, but simple enough to get the job done. Since the problem occurred on portable devices (tablets, phones), listening to &lt;code&gt;orientationchange&lt;/code&gt; seemed like a good idea as well. The &quot;solution&quot; we shipped looks rather simple:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// WORKAROUND: converting 90vh to px&lt;/span&gt;&lt;br /&gt;$element &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; $&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;.the-selector&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt; fixMobileSafariViewport&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; $element.&lt;span style=&quot;color: #660066;&quot;&gt;css&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;height&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; window.&lt;span style=&quot;color: #660066;&quot;&gt;innerHeight&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;*&lt;/span&gt; &lt;span style=&quot;color: #CC0000;&quot;&gt;0.9&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// listen to portrait/landscape changes&lt;/span&gt;&lt;br /&gt;window.&lt;span style=&quot;color: #660066;&quot;&gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;orientationchange&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; fixMobileSafariViewport&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;fixMobileSafariViewport&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;Adding this jewel of a UserAgent switch into the mix and we had the perfect recipe for being fired on the spot:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; IS_MOBILE_SAFARI_7 &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;!!&lt;/span&gt;navigator.&lt;span style=&quot;color: #660066;&quot;&gt;userAgent&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009966; font-style: italic;&quot;&gt;/i(Pad|Phone|Pod).+(Version\/7\.\d+ Mobile)/i&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;This is what we had committed to SVN (yeah, sorry, CorporateIT™). The widget we had been working on for two weeks finally alive and kicking on all our test devices. We went back to the hotel. The hotel&#039;s bar. To drown our sorrow. We knew what we just did. We added a non-scaling time bomb to our code base.&lt;/p&gt;

&lt;h2 id=&quot;solve-problem&quot;&gt;Solving The Problem&lt;/h2&gt;

&lt;p&gt;A snowball had a better chance surviving hell than above &lt;em&gt;hack&lt;/em&gt; polluting my code for more than a couple of days. While the QA (Quality Assurance) engineers were satisfied (the tool was &quot;working&quot; after all), I looked into using &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/dev.w3.org/csswg/cssom/&#039;]);&quot;  href=&quot;http://dev.w3.org/csswg/cssom/&quot;&gt;CSSOM&lt;/a&gt; to make those &lt;code&gt;vh&lt;/code&gt; to &lt;code&gt;px&lt;/code&gt; calculations more generic. We were planning on using viewport units for more things in the future, so it made sense to sacrifice another workday for this. &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/rodneyrehm/viewport-units-buggyfill&#039;]);&quot;  href=&quot;https://github.com/rodneyrehm/viewport-units-buggyfill&quot;&gt;viewport-units-buggyfill&lt;/a&gt; is the thing now running in our apps. A simple &lt;code&gt;viewportUnitsBuggyfill.init()&lt;/code&gt; and we can stop thinking about Mobile Safari&#039;s short comings.&lt;/p&gt;

&lt;p&gt;The buggyfill doesn&#039;t work on &lt;code&gt;style&lt;/code&gt; attributes. The &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/jsbin.com/EkorUJI/3/&#039;]);&quot;  href=&quot;http://jsbin.com/EkorUJI/3/&quot;&gt;adapted test&lt;/a&gt; still fails on iOS until you &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/jsbin.com/EkorUJI/4/&#039;]);&quot;  href=&quot;http://jsbin.com/EkorUJI/4/&quot;&gt;load the buggyfill&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Don&#039;t leave quick browser-bug fixes in your code base. Separate things. Try to make it as generic as possible to cover similar problems in the future.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The term &quot;Buggyfill&quot; was coined by &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/twitter.com/asciidisco&#039;]);&quot;  href=&quot;https://twitter.com/asciidisco&quot;&gt;Sebastian Golasch&lt;/a&gt;.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Fri, 24 Jan 2014 09:33:43 +0100</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/34-guid.html</guid>
    
</item>
<item>
    <title>libsass.js - An Emscripten Experiment</title>
    <link>https://blog.rodneyrehm.de/archives/33-libsass.js-An-Emscripten-Experiment.html</link>
            <category>javascript</category>
    
    <comments>https://blog.rodneyrehm.de/archives/33-libsass.js-An-Emscripten-Experiment.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=33</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=33</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;Sebastian Golasch and I set out to run the Sass compiler in the browser. Why, you ask? because we can! Or, well, we couldn&#039;t - and &lt;em&gt;that&lt;/em&gt; needed changing. We&#039;d heard about Emscripten, but never really used it. ---&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; See the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/medialize.github.io/sass.js/&#039;]);&quot;  href=&quot;http://medialize.github.io/sass.js/&quot;&gt;Sass.js demo&lt;/a&gt; and the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/rodneyrehm/libsass#readme&#039;]);&quot;  href=&quot;https://github.com/rodneyrehm/libsass#readme&quot;&gt;libsass.js repository&lt;/a&gt; for trying to compile it yourself.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;It all started with Lea&#039;s &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/twitter.com/LeaVerou/status/420994194732515328&#039;]);&quot;  href=&quot;https://twitter.com/LeaVerou/status/420994194732515328&quot;&gt;tweet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;		
&lt;div class=&quot;serendipity_oembed_rich&quot;&gt;
 
&lt;blockquote class=&quot;twitter-tweet&quot; width=&quot;550&quot;&gt;&lt;p&gt;Now I wonder if there’s any JavaScript version of &lt;a href=&quot;https://twitter.com/SassCSS&quot;&gt;@SassCSS&lt;/a&gt; that I can use for &lt;a href=&quot;https://twitter.com/dabblet&quot;&gt;@dabblet&lt;/a&gt; previewing. Long overdue.&lt;/p&gt;&amp;mdash; Lea Verou (@LeaVerou) &lt;a href=&quot;https://twitter.com/LeaVerou/statuses/420994194732515328&quot;&gt;January 8, 2014&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&quot;https://blog.rodneyrehm.de//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;/div&gt;
&lt;/p&gt;

&lt;p&gt;Sebastian (&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/twitter.com/asciidisco&#039;]);&quot;  href=&quot;https://twitter.com/asciidisco&quot;&gt;@asciidisco&lt;/a&gt;), living in the hotel room next to mine at the time, thought it would be a good idea to have another look at &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/kripken/emscripten/&#039;]);&quot;  href=&quot;https://github.com/kripken/emscripten/&quot;&gt;Emscripten&lt;/a&gt;. Emscripten is a compiler that can turn C/C++ into JavaScript. Sebastian decided to go with &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/hcatlin/sassc/&#039;]);&quot;  href=&quot;https://github.com/hcatlin/sassc/&quot;&gt;sassc&lt;/a&gt;, a CLI (Command Line Interface) wrapper for &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/hcatlin/libsass/&#039;]);&quot;  href=&quot;https://github.com/hcatlin/libsass/&quot;&gt;libsass&lt;/a&gt;. It took him a few hours but he got &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/sassc.asciidisco.com/&#039;]);&quot;  href=&quot;http://sassc.asciidisco.com/&quot;&gt;sassc running in the browser&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You might wonder why we were even considering this hassle instead of just implementing &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/sass-lang.com/&#039;]);&quot;  href=&quot;http://sass-lang.com/&quot;&gt;Sass&lt;/a&gt; in JavaScript. The original &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/nex3/sass&#039;]);&quot;  href=&quot;https://github.com/nex3/sass&quot;&gt;Sass library&lt;/a&gt; was written in Ruby. Others have tried (e.g. &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/bmavity/scss-js&#039;]);&quot;  href=&quot;https://github.com/bmavity/scss-js&quot;&gt;scss-js&lt;/a&gt;) and failed at keeping it up to date. We didn&#039;t want to add to that growing list of dead-ware™.&lt;/p&gt;

&lt;p&gt;Sebastian decided to use &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/hcatlin/sassc/&#039;]);&quot;  href=&quot;https://github.com/hcatlin/sassc/&quot;&gt;sassc&lt;/a&gt; so he wouldn&#039;t have to build an interface for the library. He&#039;s seen this approach work for &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/richardassar.github.io/pngcrush.js/&#039;]);&quot;  href=&quot;http://richardassar.github.io/pngcrush.js/&quot;&gt;pngcrush.js&lt;/a&gt; and gave it a try. While Sebastian was trying to figure out how to get the compiled program to run more than once, I started looking into emscripting libsass itself.&lt;/p&gt;

&lt;p&gt;What follows is a write up of my experiences dabbling with Emscripten. If you are not interested in that but merely care about &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/medialize.github.io/sass.js/&#039;]);&quot;  href=&quot;http://medialize.github.io/sass.js/&quot;&gt;Sass in the browser&lt;/a&gt; stop reading here.&lt;/p&gt;

&lt;h2&gt;Incident Report&lt;/h2&gt;

&lt;p&gt;Let me, very quickly, explain who I am so you have a better picture of how things went down. I&#039;ve been doing web things since 1998. I learned programming in PHP. I thought I knew C++ because I wrote a terminal based game Battleship at the University in 2006. The only exposure I had to C/C++ since, was reading through some of PHP&#039;s internals. It is 2014 and it&#039;s safe to say: I know jack shit about C/C++.&lt;/p&gt;

&lt;p&gt;The steps necessary to compile libsass to JavaScript are detailed in the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/rodneyrehm/libsass#compiling-libsassjs-yourself&#039;]);&quot;  href=&quot;https://github.com/rodneyrehm/libsass#compiling-libsassjs-yourself&quot;&gt;Readme&lt;/a&gt;. I won&#039;t repeat that here. Instead I&#039;ll explain why this endeavor took us 3 days instead of 3 hours.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I didn&#039;t know anything about the C/C++ build environment. I&#039;ve been using &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/macports.org/&#039;]);&quot;  href=&quot;http://macports.org/&quot;&gt;MacPorts&lt;/a&gt; and &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/brew.sh/&#039;]);&quot;  href=&quot;http://brew.sh/&quot;&gt;Homebrew&lt;/a&gt; for years, but only very occasionally compiled something myself. And by &quot;compiling&quot; I mean typing &lt;code&gt;make install&lt;/code&gt; or something I copied off some readme somewhere.&lt;/p&gt;

&lt;p&gt;After installing Emscripten following their instructions, I ran &lt;code&gt;emmake make&lt;/code&gt; and my terminal responded with &lt;code&gt;env: python2: No such file or directory&lt;/code&gt;. It was 01:00 (1AM) and I didn&#039;t feel like I wanted to play with this anymore. I had given up before I got started. The next morning Sebastian, who had already fixed the issue on his machine, helped me get my installation up and running. If it wasn&#039;t for Sebastian pushing me, I&#039;d not have continued pursuing libsass.js.&lt;/p&gt;

&lt;p&gt;Once &lt;code&gt;python2&lt;/code&gt; was available, and modifying the Makefile we got Emscripten to compile libsass. The problem was, the resulting file only contained the Emscripten environment. Reading &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/kripken/emscripten/wiki/Interacting-with-code#calling-compiled-functions-from-normal-javascript&#039;]);&quot;  href=&quot;https://github.com/kripken/emscripten/wiki/Interacting-with-code#calling-compiled-functions-from-normal-javascript&quot;&gt;Calling Compiled Functions From Normal JavaScript&lt;/a&gt; helped. We got a JavaScript file exposing &lt;code&gt;sass_compile()&lt;/code&gt;. The trouble was, we couldn&#039;t call it.&lt;/p&gt;

&lt;p&gt;The C++ function &lt;code&gt;sass_compile()&lt;/code&gt; expects a struct (if you&#039;re a JS person, think of a typed object) but the wiki didn&#039;t say how to handle that. Googling around we found out that working with structs is not recommended, as you&#039;d have to do &quot;all kinds of weird pointery things&quot;. At this point I decided to wrap &lt;code&gt;sass_compile()&lt;/code&gt; in another function that would construct the struct from primitive parameters. This ended up becoming &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/rodneyrehm/libsass/blob/emscripten/emscripten_wrapper.cpp&#039;]);&quot;  href=&quot;https://github.com/rodneyrehm/libsass/blob/emscripten/emscripten_wrapper.cpp&quot;&gt;emscripten_wrapper.cpp&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The road to that little function was long and bumpy. It involved consulting &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/ckruse&#039;]);&quot;  href=&quot;https://github.com/ckruse&quot;&gt;Christian Kruse&lt;/a&gt; for the most basic things. Questions like &quot;how do I copy a string&quot; seem strange to JavaScript developer, because in JS it&#039;s a simple assign. In C++, when working with C strings, you need to &lt;code&gt;#include &amp;lt;cstring&amp;gt;&lt;/code&gt; and execute &lt;code&gt;strdup()&lt;/code&gt;. To someone actually knowing C/C++ this must seem ridiculous. At the time I felt a bit more like &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/i.imgur.com/O7lpqrS.gif&#039;]);&quot;  href=&quot;http://i.imgur.com/O7lpqrS.gif&quot;&gt;this&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Anyways, after making sure the Makefile used emcc and emar (instead of g++ and ar), I was able to compile valid SCSS to CSS. YAY! For invalid SCSS I got the following JavaScript error thrown:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&quot;5323272 - Exception catching is disabled, this exception cannot be caught. Compile with -s DISABLE_EXCEPTION_CATCHING=0 or DISABLE_EXCEPTION_CATCHING=2 to catch.&quot;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I recompiled libsass.js with the proper flag and nothing happened. I got no error message and no exception. I figured the mentioned &quot;exception catching&quot; referred to something within Emscripten and had to do with passing an exception from C++ to JavaScript. This later turned out to be wrong. A day later. I wasted a day because I didn&#039;t understand that I needed to tell Emscripten that C++ code must be able to handle exceptions &lt;em&gt;internally&lt;/em&gt;. Only after &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/anarazel&#039;]);&quot;  href=&quot;https://github.com/anarazel&quot;&gt;Andres Freund&lt;/a&gt; pointed this out, did I get my error message.&lt;/p&gt;

&lt;p&gt;The error message was supposed to be returned via parameter (think &quot;call by reference&quot;). As &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/kapadia.github.io/emscripten/2013/09/13/emscripten-pointers-and-pointers.html&#039;]);&quot;  href=&quot;http://kapadia.github.io/emscripten/2013/09/13/emscripten-pointers-and-pointers.html&quot;&gt;Emscripten Pointers And Pointers&lt;/a&gt; shows, it&#039;s not as straight forward as I hoped it to be. Considering I&#039;d already wasted a day of work, I did not pursue the idea of reading data from a pointer further, but returned the error message the same way the compiled CSS came back to me. By &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/rodneyrehm/libsass/blob/ada8fb963ef9c126028bcbe25beebc043a4081ac/emscripten_wrapper.cpp#L36-L40&#039;]);&quot;  href=&quot;https://github.com/rodneyrehm/libsass/blob/ada8fb963ef9c126028bcbe25beebc043a4081ac/emscripten_wrapper.cpp#L36-L40&quot;&gt;simply returning the string&lt;/a&gt;. This is about as ugly as it can get. It did the job though. I finally had a version that either returned compiled CSS or told me what was wrong. I thought my job was done.&lt;/p&gt;

&lt;p&gt;Christian disagreed and figured out how to get all that pointery stuff working. Seeing the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/rodneyrehm/libsass#readme&#039;]);&quot;  href=&quot;https://github.com/rodneyrehm/libsass#readme&quot;&gt;working example&lt;/a&gt;, I can even make sense of it. Maybe Alon can add that to the docs? Christian also managed to modify the Makefile in a way that would allow us to send the changes back to the original libsass project.&lt;/p&gt;

&lt;h2&gt;Emscripten API&lt;/h2&gt;

&lt;p&gt;I&#039;m told people want to see code and stuff. Showing you some of the compiled libsass wouldn&#039;t satisfy that need, though. I mean, just look at this childsplay™:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;allocate&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;36&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;64&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;89&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;64&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;136&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;195&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; …&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; f&lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;g&lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;h&lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;j&lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;k&lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;f&lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt;i&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;i&lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt;i&lt;span style=&quot;color: #339933;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;24&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;g&lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt;f&lt;span style=&quot;color: #339933;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;qJ&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;g&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;c&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#91;&lt;/span&gt;d&lt;span style=&quot;color: #339933;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;|&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;z&lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt; …&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;Let&#039;s have a look at how you can access the generated libsass.js instead. After loading the file, Emscpripten will litter itself all over the global scope. A quick comparison using &lt;code&gt;Object.getOwnPropertyNames(window).length&lt;/code&gt; shows Emscripten declares ~400 (four hundred) global variables. Ouch! But then, that ~670KB light environment needs to do something, doesn&#039;t it? Short story is: you don&#039;t want this loaded in your document, but rather have it contained in a &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/developer.mozilla.org/en/docs/Web/API/Worker&#039;]);&quot;  href=&quot;https://developer.mozilla.org/en/docs/Web/API/Worker&quot;&gt;web worker&lt;/a&gt;. Seriously.&lt;/p&gt;

&lt;p&gt;So let&#039;s have a look at how you interface with a C++ function from JavaScript:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// Module is one of the gazillion variables Emscripten creates,&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// it gives you access to the environment&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; result &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; Module.&lt;span style=&quot;color: #660066;&quot;&gt;ccall&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// the name of the function to invoke&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;the_function_name&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// the data type the function will return&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;string&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// the data type the function expects as parameters&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;string&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;number&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// values to pass as arguments&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;hello world&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #CC0000;&quot;&gt;123&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;That looks pretty straight forward. That was about as far as I got from looking at various examples. It required Christian wasting another night to &quot;reverse engineer&quot; how to pass in a pointered pointer which you can read a result from:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// create pointer to pointer&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; ptr_to_ptr &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; Module.&lt;span style=&quot;color: #660066;&quot;&gt;allocate&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;i8&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; ALLOC_STACK&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// execute the C/C++ function&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; result &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; Module.&lt;span style=&quot;color: #660066;&quot;&gt;ccall&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;the_function_name&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;string&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;string&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;number&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;i8&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;hello world&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #CC0000;&quot;&gt;123&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; ptr_to_ptr&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// pull pointer from pointer&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; err_str &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; Module.&lt;span style=&quot;color: #660066;&quot;&gt;getValue&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;ptr_to_ptr&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;*&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;err_str&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// pull string from pointer&lt;/span&gt;&lt;br /&gt;&amp;#160; err_str &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; Module.&lt;span style=&quot;color: #660066;&quot;&gt;Pointer_stringify&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;err_str&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;Besides the obvious – C/C++ developers not liking CamelCase – what is happening here is quite simple, if you understand pointers. A pointer is an address to some space in memory. A pointered pointer (or pointer to a pointer) is an address to some space in memory, where an address to some space in memory is stored. A construct like a pointer to a string pointer is somewhat common in C, you allocate memory on the heap and let the parameter pointer point to this address. You would use the &lt;code&gt;&amp;amp;&lt;/code&gt; (address of) operator to give the called function the address of the variable you want to have the string stored in.&lt;/p&gt;

&lt;p&gt;Since JavaScript doesn&#039;t know pointers in this form, Emscripten has to emulate the memory management of C to be able to run such code. And I mean this literally: Emscripten takes the byte code generated by the compiler, turns it into JavaScript and emulates the necessary API to let that run. A pointer in JavaScript/Emscripten is basically just an offset for an array (think &lt;code&gt;memory[pointer]&lt;/code&gt;). Memory like you have in C is emulated in JavaScript by &quot;abusing&quot; an array. The array is the memory, the pointer (&quot;address to space&quot;) is an index of an element in that array. And in such a &quot;space&quot; we can either save data, or an address to another space. In C the stack is generated by the compiler, and the emulated memory array is generated by Emscripten.&lt;/p&gt;

&lt;p&gt;After the C++ function was executed, we retrieve the first pointers value (another pointer) from memory. If it is 0, (the numeric presentation of NULL), there is no address. Otherwise we just got another pointer that we can resolve to string (think &lt;code&gt;var address = memory[pointer]; var value = memory[address];&lt;/code&gt;) And that&#039;s it, we passed a string back to the caller via function parameter.&lt;/p&gt;

&lt;p&gt;That sounded like Klingon to you? Maybe this snippet can help explain the idea:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// objects (that is everything but primitives) are references.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// We can&#039;t do any fancy pointer arithmetic, but we can pass&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// an object into a function and have the function mutate its&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// members&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; pointer &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; nonPointer &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;mars&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt; addProperty&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;reference&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; value&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; reference.&lt;span style=&quot;color: #660066;&quot;&gt;pointer&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;world&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; value &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;jupiter&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;modifyObject&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;pointer&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console.&lt;span style=&quot;color: #660066;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;pointer.&lt;span style=&quot;color: #660066;&quot;&gt;pointer&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; value&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// &amp;quot;world&amp;quot;, &amp;quot;mars&amp;quot;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;Of course this is &lt;em&gt;not even remotely the same thing&lt;/em&gt;. But I think it illustrates the mechanics – or rather basic idea – of pointered pointers quite nicely.&lt;/p&gt;

&lt;h3&gt;JavaScript API sass.js&lt;/h3&gt;

&lt;p&gt;We realized that working with the Emscripten API was going to turn people down. Hell, it turned &lt;em&gt;me&lt;/em&gt; down. If anyone was actually going to use this thing, it needed a nice-enough API, so we created &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/medialize/sass.js&#039;]);&quot;  href=&quot;https://github.com/medialize/sass.js&quot;&gt;Sass.js&lt;/a&gt;. And there you have it, Sass in the browser:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; scss &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;$someVar: 123px; .some-selector { width: $someVar; }&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; css &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; Sass.&lt;span style=&quot;color: #660066;&quot;&gt;compile&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;scss&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console.&lt;span style=&quot;color: #660066;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;css&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// .some-selector{&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// &amp;#160; width: 123px; }&lt;/span&gt;&lt;/div&gt;

&lt;h3&gt;Using the Filesystem&lt;/h3&gt;

&lt;p&gt;Sass has a feature to include other files using &lt;code&gt;@import &quot;path/to/file&quot;;&lt;/code&gt;. In our projects we use this quite frequently, because it allows us to split a larger style code base into small modules. I wanted this feature to work in the browser as well. Luckily Emscripten comes with it&#039;s own filesystem. This is &lt;em&gt;not&lt;/em&gt; the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/developer.mozilla.org/en-US/docs/WebGuide/API/File_System/Introduction&#039;]);&quot;  href=&quot;https://developer.mozilla.org/en-US/docs/WebGuide/API/File_System/Introduction&quot;&gt;File System API&lt;/a&gt;. The Emscripten environment offers low-level filesystem access, for example:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;FS.&lt;span style=&quot;color: #660066;&quot;&gt;writeFile&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;/test.txt&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;Hello World&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;encoding&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;utf8&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; result &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; FS.&lt;span style=&quot;color: #660066;&quot;&gt;readFile&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;/test&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;encoding&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;utf8&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console.&lt;span style=&quot;color: #660066;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;result&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// &amp;quot;Hello World&amp;quot;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;If you were to &lt;code&gt;writeFile()&lt;/code&gt; to a path that doesn&#039;t exist, the function throws an error. You can create directories using &lt;code&gt;FS.mkdir(&#039;/some-path&#039;);&lt;/code&gt;. In this instance low-level means that mkdir doesn&#039;t support recursively creating parent directories, so &lt;code&gt;FS.mkdir(&#039;/some/path/hello/world&#039;)&lt;/code&gt; will throw an Error. While these functions allow you to implement pretty much everything you want to, they&#039;re not particularly convenient.&lt;/p&gt;

&lt;p&gt;By the way, finding out which functions &lt;code&gt;FS&lt;/code&gt; provided and what they did was figured out by using Chrome&#039;s DevTools. Executing &lt;code&gt;FS.readFile&lt;/code&gt; in the console is the same as running &lt;code&gt;console.log(String(FS.readfile))&lt;/code&gt; – it dumps the function&#039;s source code to the console. Because the DevTools approach worked so well, I can&#039;t even tell you if Emscripten&#039;s &lt;code&gt;FS&lt;/code&gt; is documented anywhere. But we didn&#039;t want developers to have to figure out things on their own. Therefore we added file-support to Sass.js, hiding the ugly parts:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;Sass.&lt;span style=&quot;color: #660066;&quot;&gt;writeFile&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;/unknown/path/test.scss&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;.selector { content: &amp;quot;hello world&amp;quot;; }&#039;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;With that we can make &lt;code&gt;@import&lt;/code&gt; directives work in the browser:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// enable line comments&lt;/span&gt;&lt;br /&gt;Sass.&lt;span style=&quot;color: #660066;&quot;&gt;options&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt; comments&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;true&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// add some files&lt;/span&gt;&lt;br /&gt;Sass.&lt;span style=&quot;color: #660066;&quot;&gt;writeFile&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;one.scss&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;.one { width: 123px; }&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;Sass.&lt;span style=&quot;color: #660066;&quot;&gt;writeFile&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;some-dir/two.scss&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;.two { width: 123px; }&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// compile the imports&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; css &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; Sass.&lt;span style=&quot;color: #660066;&quot;&gt;compile&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;@import &amp;quot;one&amp;quot;; @import &amp;quot;some-dir/two&amp;quot;;&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;console.&lt;span style=&quot;color: #660066;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;css&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;resulting in the following output:&lt;/p&gt;

&lt;div class=&quot;css geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;/* line 1, /sass/one */&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #6666ff;&quot;&gt;.one&lt;/span&gt; &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;123px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;/* line 1, /sass/some-dir/two */&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #6666ff;&quot;&gt;.two&lt;/span&gt; &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;123px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;There&#039;s even a &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/medialize.github.io/sass.js/linked.html&#039;]);&quot;  href=&quot;http://medialize.github.io/sass.js/linked.html&quot;&gt;demo trying out loading individual SCSS files&lt;/a&gt; from the server and composing things in the browser. We&#039;re not quite there yet, but we actually had to get back to our jobs at some point.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Before any of this got published I contacted Lea so she could point out what needed fixing before &quot;going live&quot;. It took her all but 3 minutes to find something. Turns out libsass has problems with &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/hcatlin/libsass/issues/246&#039;]);&quot;  href=&quot;https://github.com/hcatlin/libsass/issues/246&quot;&gt;interpolation&lt;/a&gt;. Not &lt;em&gt;our&lt;/em&gt; problem - thank the Lords of &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/en.wikipedia.org/wiki/Lords_of_Kobol&#039;]);&quot;  href=&quot;http://en.wikipedia.org/wiki/Lords_of_Kobol&quot;&gt;Kobol&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Emscripten is a hell of a tool - if you know what you&#039;re doing. It&#039;s lacking - easily findable - documentation on how to interact with compiled code. I mean &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/kripken/emscripten/wiki/Interacting-with-code#calling-compiled-functions-from-normal-javascript&#039;]);&quot;  href=&quot;https://github.com/kripken/emscripten/wiki/Interacting-with-code#calling-compiled-functions-from-normal-javascript&quot;&gt;Interacting with Code&lt;/a&gt; is a great start, but doesn&#039;t cover &quot;basic&quot; things like structs and pointered parameters all that well.&lt;/p&gt;

&lt;p&gt;Huge thanks go to Alon, Andres, Christian and Sebastian for making this work. I did all the failing so you guys could work things out. It was fun. Let&#039;s (not) repeat this (any time soon) ☺&lt;/p&gt;

&lt;p&gt;Now go see the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/medialize.github.io/sass.js/&#039;]);&quot;  href=&quot;http://medialize.github.io/sass.js/&quot;&gt;Sass.js demo&lt;/a&gt; and the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/rodneyrehm/libsass#readme&#039;]);&quot;  href=&quot;https://github.com/rodneyrehm/libsass#readme&quot;&gt;libsass repository&lt;/a&gt; for trying to compile it yourself. Try shit out. Fail at things. Have fun. Sweat over compile errors at 2PM. Do things.&lt;/p&gt;

&lt;p&gt;P.S. I really suck at C/C++.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Wed, 15 Jan 2014 12:39:39 +0100</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/33-guid.html</guid>
    
</item>
<item>
    <title>Updating to iScroll 5</title>
    <link>https://blog.rodneyrehm.de/archives/32-Updating-to-iScroll-5.html</link>
            <category>javascript</category>
    
    <comments>https://blog.rodneyrehm.de/archives/32-Updating-to-iScroll-5.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=32</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=32</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/cubiq/iscroll&#039;]);&quot;  href=&quot;https://github.com/cubiq/iscroll&quot;&gt;iScroll&lt;/a&gt;, the number one widget for managing scrollable panels, has been available in version 5 &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/cubiq.org/fyi-iscroll-is-out-of-beta&#039;]);&quot;  href=&quot;http://cubiq.org/fyi-iscroll-is-out-of-beta&quot;&gt;since October&lt;/a&gt;. This post documents my pain updating to iScroll 5.0.9. We&#039;ve been using iScroll for ages. We&#039;ve been using it long before we moved to package managers (&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/npmjs.org/&#039;]);&quot;  href=&quot;http://npmjs.org/&quot;&gt;npm&lt;/a&gt; and &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/bower.io/&#039;]);&quot;  href=&quot;http://bower.io/&quot;&gt;bower&lt;/a&gt;) and it so happened that the library got stuck at version 4.2.5. A patched version. A patched version of a patched version. A dark and ugly corner of our app infrastructure.&lt;/p&gt;

&lt;p&gt;I considered the update important because of 3 things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I don&#039;t like stale (as in untracked) dependencies&lt;/li&gt;
&lt;li&gt;I don&#039;t like patched dependencies&lt;/li&gt;
&lt;li&gt;Version 5 comes with &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.w3.org/TR/pointerevents/&#039;]);&quot;  href=&quot;http://www.w3.org/TR/pointerevents/&quot;&gt;&lt;code&gt;PointerEvents&lt;/code&gt;&lt;/a&gt; support, interactive scrollbars, and quite a number of enhancements&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p&gt;I&#039;ve looked at the source and it made a good impression. It&#039;s clean, well structured, moderately simple and easy to understand. From a coding perspective a job very well done. That said, I spent most of the afternoon cursing. Good code is one thing, completely missing documentation, changelog and upgrade guide paint a different picture.&lt;/p&gt;

&lt;p&gt;Anyway, &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/twitter.com/cubiq/&#039;]);&quot;  href=&quot;https://twitter.com/cubiq/&quot;&gt;Matteo&lt;/a&gt; is working on it. As many of the smaller open source tools are side projects, they have to be dealt with in the author&#039;s personal time. Matteo is spending his Christmas holiday on writing the docs for iScroll 5. The official documentation (including tutorials) should be available early 2014. Until then I hope this post can help ease your upgrade pains.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Back to updating iScroll…&lt;/p&gt;

&lt;h2&gt;Changed API&lt;/h2&gt;

&lt;p&gt;The first breaking change is its name — it used to be &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/cubiq/iscroll/blob/d31d6e6ff798a8adc572879549ac1a3e2f47a01e/src/iscroll.js#L1102&#039;]);&quot;  href=&quot;https://github.com/cubiq/iscroll/blob/d31d6e6ff798a8adc572879549ac1a3e2f47a01e/src/iscroll.js#L1102&quot;&gt;&lt;code&gt;window.iScroll&lt;/code&gt;&lt;/a&gt;, it now is &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/cubiq/iscroll/blob/a83b52eecd1eb250892a4a9c95de3601f67b1a57/build/iscroll.js#L1973&#039;]);&quot;  href=&quot;https://github.com/cubiq/iscroll/blob/a83b52eecd1eb250892a4a9c95de3601f67b1a57/build/iscroll.js#L1973&quot;&gt;&lt;code&gt;window.IScroll&lt;/code&gt;&lt;/a&gt;. I&#039;m just going to leave this here, without debating naming conventions.&lt;/p&gt;

&lt;p&gt;iScroll 4 would accept a string as the element to scroll in &lt;code&gt;new iScroll(&quot;id-of-wrapper&quot;);&lt;/code&gt;, version 5 uses &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/developer.mozilla.org/en-US/docs/Web/API/document.querySelector&#039;]);&quot;  href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/document.querySelector&quot;&gt;querySelector()&lt;/a&gt; and thus needs a hash &lt;code&gt;new IScroll(&quot;#id-of-wrapper&quot;);&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;No AMD support&lt;/h2&gt;

&lt;p&gt;Version 5 still only supports CommonJS modules, so AMD style systems like &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/requirejs.org/&#039;]);&quot;  href=&quot;http://requirejs.org/&quot;&gt;RequireJS&lt;/a&gt; have to be shimmed:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;require.&lt;span style=&quot;color: #660066;&quot;&gt;config&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; paths&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;iscroll&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;path/to/iscroll&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&amp;#160; shim&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;iscroll&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;exports&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;IScroll&amp;quot;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;h2&gt;Changed Styling&lt;/h2&gt;

&lt;p&gt;The scrollable content bled through the boundary. iScroll 4 used to &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/cubiq/iscroll/blob/d31d6e6ff798a8adc572879549ac1a3e2f47a01e/src/iscroll.js#L89&#039;]);&quot;  href=&quot;https://github.com/cubiq/iscroll/blob/d31d6e6ff798a8adc572879549ac1a3e2f47a01e/src/iscroll.js#L89&quot;&gt;add &lt;code&gt;overflow: hidden&lt;/code&gt;&lt;/a&gt; to the wrapping element - iScroll 5 does &lt;em&gt;not&lt;/em&gt;. Add &lt;code&gt;overflow:hidden&lt;/code&gt; (or &lt;code&gt;overflow-x:hidden&lt;/code&gt;) to whatever element you initialize iScroll for.&lt;/p&gt;

&lt;h2&gt;Option Properties&lt;/h2&gt;

&lt;p&gt;A lot, if not most, of the option properties known to iScroll 4 have been renamed in iScroll 5. What used to be called &lt;code&gt;hScroll&lt;/code&gt; is now known as &lt;code&gt;scrollX&lt;/code&gt; — still a boolean advising if the horizontal axis can be scrolled or not. Here&#039;s an incomplete map of changed names:&lt;/p&gt;

&lt;table&gt;&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;iScroll 4 property&lt;/th&gt;&lt;th&gt;iScroll 5 property&lt;/th&gt;&lt;th&gt;description&lt;/th&gt;&lt;/tr&gt; 
&lt;/thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;hScroll&lt;/td&gt;&lt;td&gt;scrollX&lt;/td&gt;&lt;td&gt;(boolean) allow horizontal scrolling&lt;/td&gt;&lt;/tr&gt; 
&lt;tr&gt;&lt;td&gt;vScroll&lt;/td&gt;&lt;td&gt;scrollY&lt;/td&gt;&lt;td&gt;(boolean) allow vertical scrolling&lt;/td&gt;&lt;/tr&gt; 
&lt;tr&gt;&lt;td&gt;vScrollbar&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;render vertical scrollbar&lt;/td&gt;&lt;/tr&gt; 
&lt;tr&gt;&lt;td&gt;hScrollbar&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;render horizontal scrollbar&lt;/td&gt;&lt;/tr&gt; 
&lt;tr&gt;&lt;td&gt;hideScrollbar&lt;/td&gt;&lt;td&gt;scrollbars&lt;/td&gt;&lt;td&gt;(boolean) render scrollbars or not - inverted meaning&lt;/td&gt;&lt;/tr&gt; 
&lt;tr&gt;&lt;td&gt;draggableScrollbars&lt;/td&gt;&lt;td&gt;interactiveScrollbars&lt;/td&gt;&lt;td&gt;(boolean) make scrollbars tangible&lt;/td&gt;&lt;/tr&gt; 
&lt;tr&gt;&lt;td&gt;lockDirection&lt;/td&gt;&lt;td&gt;freeScroll&lt;/td&gt;&lt;td&gt;(boolean) if scrolling one direction, lock the other - inverted meaning&lt;/td&gt;&lt;/tr&gt; 
&lt;tr&gt;&lt;td&gt;wheelAction&lt;/td&gt;&lt;td&gt;mouseWheel&lt;/td&gt;&lt;td&gt;(string &quot;scroll&quot;|&quot;zoom&quot;) controlling the reaction to the mouse wheel&lt;/td&gt;&lt;/tr&gt; 
&lt;tr&gt;&lt;td&gt;handleClick&lt;/td&gt;&lt;td&gt;tap, click&lt;/td&gt;&lt;td&gt;(boolean) issue click/tap events&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;Without spending too much time on reading the source, I can&#039;t say I fully understand what each and every option&#039;s side effects are. For example some kind of &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/cubiq/iscroll/blob/a83b52eecd1eb250892a4a9c95de3601f67b1a57/build/iscroll-zoom.js#L900&#039;]);&quot;  href=&quot;https://github.com/cubiq/iscroll/blob/a83b52eecd1eb250892a4a9c95de3601f67b1a57/build/iscroll-zoom.js#L900&quot;&gt;&quot;custom styling&quot;&lt;/a&gt; is triggered for &lt;code&gt;scrollbar&lt;/code&gt; not being a string. But if it&#039;s a string, besides not &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/cubiq/iscroll/blob/a83b52eecd1eb250892a4a9c95de3601f67b1a57/build/iscroll-zoom.js#L1739&#039;]);&quot;  href=&quot;https://github.com/cubiq/iscroll/blob/a83b52eecd1eb250892a4a9c95de3601f67b1a57/build/iscroll-zoom.js#L1739&quot;&gt;triggering the default style&lt;/a&gt; I can&#039;t see what should happen with that string… We&#039;re not using custom styles, so I had to quit investigating at some point — sorry.&lt;/p&gt;

&lt;p&gt;Note: The option &lt;code&gt;useTransition&lt;/code&gt; used to default to &lt;code&gt;false&lt;/code&gt; in iScroll 4, version 5 enables this by default.&lt;/p&gt;

&lt;p&gt;Have a look at the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/cubiq/iscroll/tree/master/demos&#039;]);&quot;  href=&quot;https://github.com/cubiq/iscroll/tree/master/demos&quot;&gt;demos&lt;/a&gt; to quickly figure out what options you need to pass. The way we use iScroll most is rather simple:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; scroller &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;new&lt;/span&gt; IScroll&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;scrollableElement&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// scroll only vertically&lt;/span&gt;&lt;br /&gt;&amp;#160; scrollX&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&amp;#160; scrollY&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// paint scrollbars&lt;/span&gt;&lt;br /&gt;&amp;#160; scrollbars&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// make scrollbars draggable&lt;/span&gt;&lt;br /&gt;&amp;#160; interactiveScrollbars&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// allow scrolling by wheel&lt;/span&gt;&lt;br /&gt;&amp;#160; mouseWheel&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;true&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;h2&gt;Callbacks vs. Events&lt;/h2&gt;

&lt;p&gt;In iScroll 4 we would register a function to be triggered after a scroll operation had finished, like so:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; scroller &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;new&lt;/span&gt; iScroll&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;element&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// ... options ...&lt;/span&gt;&lt;br /&gt;&amp;#160; onScrollEnd&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; console.&lt;span style=&quot;color: #660066;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;scolled!&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;in iScroll 5 there all the callbacks have been replaced by events:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; scroller &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;new&lt;/span&gt; IScroll&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;element&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// ... options ...&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;scroller.&lt;span style=&quot;color: #660066;&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;scrollEnd&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; console.&lt;span style=&quot;color: #660066;&quot;&gt;log&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;scolled!&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;The same is true for &lt;code&gt;scrollEnd&lt;/code&gt;, &lt;code&gt;scrollCancel&lt;/code&gt;, &lt;code&gt;scrollStart&lt;/code&gt;, &lt;code&gt;beforeScrollStart&lt;/code&gt;, &lt;code&gt;refresh&lt;/code&gt; and &lt;code&gt;destroy&lt;/code&gt;. Also a new event called &lt;code&gt;flick&lt;/code&gt; was added.&lt;/p&gt;

&lt;p&gt;The built file &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/cubiq/iscroll/blob/a83b52eecd1eb250892a4a9c95de3601f67b1a57/build/iscroll-zoom.js&#039;]);&quot;  href=&quot;https://github.com/cubiq/iscroll/blob/a83b52eecd1eb250892a4a9c95de3601f67b1a57/build/iscroll-zoom.js&quot;&gt;&lt;code&gt;build/iscroll-zoom.js&lt;/code&gt;&lt;/a&gt; additionally knows the events &lt;code&gt;zoomStart&lt;/code&gt; and &lt;code&gt;zoomEnd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since I couldn&#039;t find anything in the source, I fear the following callbacks have been removed entirely: &lt;code&gt;onBeforeScrollMove&lt;/code&gt;, &lt;code&gt;onScrollMove&lt;/code&gt;, &lt;code&gt;onBeforeScrollEnd&lt;/code&gt;, &lt;code&gt;onTouchEnd&lt;/code&gt;, &lt;code&gt;onZoom&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;Preventing Default&lt;/h2&gt;

&lt;p&gt;In case that never bit you, iScroll 4 called &lt;code&gt;event.preventDefault()&lt;/code&gt; for pretty much every event, essentially making it impossible to focus form elements. We got around that by doing things like the following, to allow a &lt;code&gt;&amp;lt;textarea&amp;gt;&lt;/code&gt; to be focused, even if they were inside an iScroll container:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; scroller &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;new&lt;/span&gt; iScroll&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;element&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// ... options ...&lt;/span&gt;&lt;br /&gt;&amp;#160; onBeforeScrollStart&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;event&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// do not preventDefault() for &amp;lt;textarea&amp;gt;s, as that makes them unfocusable&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;event.&lt;span style=&quot;color: #660066;&quot;&gt;target&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;nodeName&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;toLowerCase&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;!==&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;textarea&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; event.&lt;span style=&quot;color: #660066;&quot;&gt;preventDefault&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;iScroll 5 deals with this differently. It has an option &lt;code&gt;preventDefaultException&lt;/code&gt; that comes with a default value of &lt;code&gt;{ tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ }&lt;/code&gt;. With this you can run any (string) property of &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/developer.mozilla.org/en/docs/Web/API/HTMLElement&#039;]);&quot;  href=&quot;https://developer.mozilla.org/en/docs/Web/API/HTMLElement&quot;&gt;HTMLElement&lt;/a&gt; through a filter, preventing the &lt;code&gt;preventDefault()&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; scroller &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;new&lt;/span&gt; IScroll&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;element&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// ... options ...&lt;/span&gt;&lt;br /&gt;&amp;#160; preventDefaultException&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// default config, all form elements,&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// extended with a WebComponents Custom Element from the future&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; tagName&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #009966; font-style: italic;&quot;&gt;/^(INPUT|TEXTAREA|BUTTON|SELECT|X-WIDGET)$/&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// and allow any element that has an accessKey (because we can)&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; accessKey&lt;span style=&quot;color: #339933;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #009966; font-style: italic;&quot;&gt;/.+/&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;iScroll 5 is a solid improvement over iScroll 4. It&#039;s currently lacking the docs to upgrade easily, but that stuff is coming. Until then I hope the pointers in this post can get you started updating today.&lt;/p&gt;

&lt;p&gt;Now go read &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/cubiq.org/iscroll-a-small-moan&#039;]);&quot;  href=&quot;http://cubiq.org/iscroll-a-small-moan&quot;&gt;iScroll, a small moan&lt;/a&gt; and do something about it. Ask your employer to give you some time to help with the project, or better yet, ask them to support the project financially. God knows your product has benefited from Matteo&#039;s work.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Tue, 31 Dec 2013 13:40:00 +0100</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/32-guid.html</guid>
    
</item>
<item>
    <title>(My) Best Of 2013 Conference Talks</title>
    <link>https://blog.rodneyrehm.de/archives/31-My-Best-Of-2013-Conference-Talks.html</link>
    
    <comments>https://blog.rodneyrehm.de/archives/31-My-Best-Of-2013-Conference-Talks.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=31</wfw:comment>

    <slash:comments>1</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=31</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;The 15 conference talks of 2013 I liked most. ---&lt;/p&gt;

&lt;p&gt;[April] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/2013.front-trends.com/&#039;]);&quot;  href=&quot;http://2013.front-trends.com/&quot;&gt;Front-Trends 2013&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/leaverou.com/&#039;]);&quot;  href=&quot;http://leaverou.com/&quot;&gt;Lea Verous&lt;/a&gt; talked about the Border-Radius. (Video from same talk at CSS Day)
  
&lt;div class=&quot;serendipity_oembed&quot;&gt;
&lt;a href=&quot;https://vimeo.com/70171266&quot; target=&quot;_blank&quot;&gt;https://vimeo.com/70171266&lt;/a&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/front-trends/scfkhf/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/front-trends/scfkhf/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[April] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/2013.front-trends.com/&#039;]);&quot;  href=&quot;http://2013.front-trends.com/&quot;&gt;Front-Trends 2013&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/jakearchibald.com/&#039;]);&quot;  href=&quot;http://jakearchibald.com/&quot;&gt;Jake Archibald&lt;/a&gt; talked about rendering performance.
  
&lt;div class=&quot;serendipity_oembed&quot;&gt;
&lt;a href=&quot;https://vimeo.com/67050197&quot; target=&quot;_blank&quot;&gt;https://vimeo.com/67050197&lt;/a&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/front-trends/scfkgd/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/front-trends/scfkgd/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[May] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/2013.beyondtellerrand.com/&#039;]);&quot;  href=&quot;http://2013.beyondtellerrand.com/&quot;&gt;Beyond Tellerrand 2013&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/adactio.com/&#039;]);&quot;  href=&quot;http://adactio.com/&quot;&gt;Jeremy Keith&lt;/a&gt; opened the show, setting the mood for thinking longer term.
  
&lt;div class=&quot;serendipity_oembed&quot;&gt;
&lt;a href=&quot;https://vimeo.com/68352550&quot; target=&quot;_blank&quot;&gt;https://vimeo.com/68352550&lt;/a&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/btconf/scgmdd/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/btconf/scgmdd/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[May] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/2013.beyondtellerrand.com/&#039;]);&quot;  href=&quot;http://2013.beyondtellerrand.com/&quot;&gt;Beyond Tellerrand 2013&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/christianheilmann.com/&#039;]);&quot;  href=&quot;http://christianheilmann.com/&quot;&gt;Christian Heilmann&lt;/a&gt; talked about Fixing The Mobile Web.
  
&lt;div class=&quot;serendipity_oembed&quot;&gt;
&lt;a href=&quot;https://vimeo.com/69790729&quot; target=&quot;_blank&quot;&gt;https://vimeo.com/69790729&lt;/a&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/btconf/scfffh/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/btconf/scfffh/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[June] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/cssday.nl/&#039;]);&quot;  href=&quot;http://cssday.nl/&quot;&gt;CSS Day&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.xanthir.com/blog/&#039;]);&quot;  href=&quot;http://www.xanthir.com/blog/&quot;&gt;Tab Atkins&lt;/a&gt; explained CSS Variables and Conditions
  
&lt;div class=&quot;serendipity_oembed&quot;&gt;
&lt;a href=&quot;https://vimeo.com/69531455&quot; target=&quot;_blank&quot;&gt;https://vimeo.com/69531455&lt;/a&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/cssday/scfzdp/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/cssday/scfzdp/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[August] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/2013.frontendconf.ch/&#039;]);&quot;  href=&quot;http://2013.frontendconf.ch/&quot;&gt;Frontend Conference Zurich 2013&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/rachelnabors.com/&#039;]);&quot;  href=&quot;http://rachelnabors.com/&quot;&gt;Rachel Nabors&lt;/a&gt; showed us how to create music videos in browser-land.
  
&lt;div class=&quot;serendipity_oembed&quot;&gt;
&lt;a href=&quot;https://www.ustream.tv/recorded/37995827&quot; target=&quot;_blank&quot;&gt;https://www.ustream.tv/recorded/37995827&lt;/a&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/fec13/scmzth/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/fec13/scmzth/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[August] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/2013.frontendconf.ch/&#039;]);&quot;  href=&quot;http://2013.frontendconf.ch/&quot;&gt;Frontend Conference Zurich 2013&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/mikewest.org/&#039;]);&quot;  href=&quot;https://mikewest.org/&quot;&gt;Mike West&lt;/a&gt; talked about Locking the front door: browser-side security.
  
&lt;div class=&quot;serendipity_oembed&quot;&gt;
&lt;a href=&quot;https://www.ustream.tv/recorded/38005119&quot; target=&quot;_blank&quot;&gt;https://www.ustream.tv/recorded/38005119&lt;/a&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/fec13/scmzrw/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/fec13/scmzrw/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[September] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/2013.fromthefront.it/&#039;]);&quot;  href=&quot;http://2013.fromthefront.it/&quot;&gt;From The Front 2013&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/brucelawson.co.uk/&#039;]);&quot;  href=&quot;http://brucelawson.co.uk/&quot;&gt;Bruce Lawson&lt;/a&gt; talked about How To Destroy The Web. A sarcastic view at how we build the web today. If you&#039;re a web professional, you&#039;re not going to learn anything here - but it&#039;s entertaining none the less. (Sadly From The Front did not (yet?) make any videos available, so here&#039;s Bruce giving the same talk at FOWA London.)
	
&lt;div class=&quot;serendipity_oembed_video&quot;&gt;
&lt;iframe width=&quot;550&quot; height=&quot;309&quot; src=&quot;https://www.youtube.com/embed/FshXcSb2Gec?feature=oembed&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/fromthefront/scmtmg/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/fromthefront/scmtmg/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[October] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/fronteers.nl/congres/2013&#039;]);&quot;  href=&quot;http://fronteers.nl/congres/2013&quot;&gt;Fronteers 2013&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/brucelawson.co.uk/&#039;]);&quot;  href=&quot;http://brucelawson.co.uk/&quot;&gt;Bruce Lawson&lt;/a&gt; talked about What The Web Needs Next. In this talk you&#039;ll find a perspective on DRM you probably haven&#039;t thought about - at least I hadn&#039;t.
  
&lt;div class=&quot;serendipity_oembed&quot;&gt;
&lt;a href=&quot;https://vimeo.com/77953783&quot; target=&quot;_blank&quot;&gt;https://vimeo.com/77953783&lt;/a&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/fronteers/scqhbq/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/fronteers/scqhbq/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[October] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/fronteers.nl/congres/2013&#039;]);&quot;  href=&quot;http://fronteers.nl/congres/2013&quot;&gt;Fronteers 2013&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/domenicdenicola.com/&#039;]);&quot;  href=&quot;http://domenicdenicola.com/&quot;&gt;Domenic Denicola&lt;/a&gt; talked about The State Of JavaScript.
  
&lt;div class=&quot;serendipity_oembed&quot;&gt;
&lt;a href=&quot;https://vimeo.com/77953785&quot; target=&quot;_blank&quot;&gt;https://vimeo.com/77953785&lt;/a&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/fronteers/scmhkp/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/fronteers/scmhkp/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[October] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/fronteers.nl/congres/2013&#039;]);&quot;  href=&quot;http://fronteers.nl/congres/2013&quot;&gt;Fronteers 2013&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/marcosc.com/&#039;]);&quot;  href=&quot;http://marcosc.com/&quot;&gt;Marcos Caceres&lt;/a&gt; explained the state of Responsive Images. I don&#039;t care too much for responsive images as a thing, but in this talk Marcos managed to explain a couple of things surrounding the standardization process.
  
&lt;div class=&quot;serendipity_oembed&quot;&gt;
&lt;a href=&quot;https://vimeo.com/77953782&quot; target=&quot;_blank&quot;&gt;https://vimeo.com/77953782&lt;/a&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/fronteers/scmhkm/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/fronteers/scmhkm/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[October] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/border-none.net/&#039;]);&quot;  href=&quot;http://border-none.net/&quot;&gt;Border:None&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/adactio.com/&#039;]);&quot;  href=&quot;http://adactio.com/&quot;&gt;Jeremy Keith&lt;/a&gt; talked about the Power Of Simplicity.
  
&lt;div class=&quot;serendipity_oembed&quot;&gt;
&lt;a href=&quot;https://vimeo.com/79556632&quot; target=&quot;_blank&quot;&gt;https://vimeo.com/79556632&lt;/a&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/border-none/scqhrc/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/border-none/scqhrc/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[October] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/border-none.net/&#039;]);&quot;  href=&quot;http://border-none.net/&quot;&gt;Border:None&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/bastianallgeier.com/&#039;]);&quot;  href=&quot;http://bastianallgeier.com/&quot;&gt;Bastian Allgeier&lt;/a&gt; talked about building a better web. &quot;Better&quot; meaning solving the problem of data silos and not owning your personal data.
  
&lt;div class=&quot;serendipity_oembed&quot;&gt;
&lt;a href=&quot;https://vimeo.com/78798346&quot; target=&quot;_blank&quot;&gt;https://vimeo.com/78798346&lt;/a&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/border-none/scpxbw/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/border-none/scpxbw/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[November] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/2013.full-frontal.org/&#039;]);&quot;  href=&quot;http://2013.full-frontal.org/&quot;&gt;Full Frontal 2013&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/kenneth.io/&#039;]);&quot;  href=&quot;http://kenneth.io/&quot;&gt;Kenneth Auchenberg&lt;/a&gt; introduced us to &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/remotedebug.org/&#039;]);&quot;  href=&quot;http://remotedebug.org/&quot;&gt;RemodeDebug&lt;/a&gt;, his initiative to make developer tools work cross-browser. I liked this talk because I had always been annoyed by the situation, but never figured we (the developer world) could do something about it.
	
&lt;div class=&quot;serendipity_oembed_video&quot;&gt;
&lt;iframe width=&quot;550&quot; height=&quot;309&quot; src=&quot;https://www.youtube.com/embed/ctwEcZC_mmI?feature=oembed&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/full-frontal/scmryh/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/full-frontal/scmryh/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;[December] At &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/2013.playandmake.com/&#039;]);&quot;  href=&quot;http://2013.playandmake.com/&quot;&gt;Beyond Tellerrand Play &#039;n&#039; Make 2013&lt;/a&gt; &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.jaredficklin.com/&#039;]);&quot;  href=&quot;http://www.jaredficklin.com/&quot;&gt;Jared Ficklin&lt;/a&gt; exposed us to Thinking By Making. 
  
&lt;div class=&quot;serendipity_oembed&quot;&gt;
&lt;a href=&quot;https://vimeo.com/82173290&quot; target=&quot;_blank&quot;&gt;https://vimeo.com/82173290&lt;/a&gt;
&lt;/div&gt;

&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lanyrd.com/2013/btplay/scpmcz/&#039;]);&quot;  href=&quot;http://lanyrd.com/2013/btplay/scpmcz/&quot;&gt;Talk on Lanyrd&lt;/a&gt;&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Sun, 29 Dec 2013 12:59:22 +0100</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/31-guid.html</guid>
    
</item>
<item>
    <title>CSS-Polyfill-Preprocessor — It's A Myth</title>
    <link>https://blog.rodneyrehm.de/archives/30-CSS-Polyfill-Preprocessor-Its-A-Myth.html</link>
    
    <comments>https://blog.rodneyrehm.de/archives/30-CSS-Polyfill-Preprocessor-Its-A-Myth.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=30</wfw:comment>

    <slash:comments>3</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=30</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;I want to share some thoughts on &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.myth.io/&#039;]);&quot;  href=&quot;http://www.myth.io/&quot;&gt;Myth.io&lt;/a&gt; — specifically its key idea of being a &quot;CSS polyfill&quot;. The short story is: Pretending to be CSS but not matching its power &lt;em&gt;will&lt;/em&gt; confuse people.&lt;/p&gt;

&lt;p&gt;Myth is a CSS Preprocessor (like &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/sass-lang.com/&#039;]);&quot;  href=&quot;http://sass-lang.com/&quot;&gt;Sass&lt;/a&gt;, &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/lesscss.org/&#039;]);&quot;  href=&quot;http://lesscss.org/&quot;&gt;LESS&lt;/a&gt;, &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/learnboost.github.io/stylus/&#039;]);&quot;  href=&quot;http://learnboost.github.io/stylus/&quot;&gt;Stylus&lt;/a&gt; or one of the other five thousand). It wants to set itself apart from the existing tools by claiming to be &quot;like a CSS polyfill&quot;. Only that, it&#039;s not, not really. It uses the &lt;em&gt;syntax&lt;/em&gt; of modern CSS, without being (remotely) able to offer the &lt;em&gt;functionality&lt;/em&gt; of modern CSS.&lt;/p&gt;

&lt;p&gt;At work we use Sass (&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/compass-style.org/&#039;]);&quot;  href=&quot;http://compass-style.org/&quot;&gt;Compass&lt;/a&gt; actually, but we&#039;re trying to get rid of the ruby dependency…). One of the many helpful things provided by a preprocessor has been the ability to use &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/sass-lang.com/documentation/file.Sass_REFERENCE.html#variables_&#039;]);&quot;  href=&quot;http://sass-lang.com/documentation/file.Sass_REFERENCE.html#variables_&quot;&gt;variables&lt;/a&gt; and do math (&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/sass-lang.com/documentation/file.Sass_REFERENCE.html#number_operations&#039;]);&quot;  href=&quot;http://sass-lang.com/documentation/file.Sass_REFERENCE.html#number_operations&quot;&gt;Number Operations&lt;/a&gt;) in &quot;CSS&quot;.&lt;/p&gt;

&lt;h2&gt;Ambiguous Math&lt;/h2&gt;

&lt;p&gt;In Sass I can easily spot where a computation is happening. The first line, being invalid CSS, is handled by the preprocessor, the second line is handed to the browser.&lt;/p&gt;

&lt;div class=&quot;css geshi&quot; style=&quot;text-align: left&quot;&gt;div &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;100px&lt;/span&gt; - &lt;span style=&quot;color: #933;&quot;&gt;50px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; calc&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #933;&quot;&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;100&lt;/span&gt;%&lt;/span&gt; - &lt;span style=&quot;color: #933;&quot;&gt;50px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;In Myth both statements look the same:&lt;/p&gt;

&lt;div class=&quot;css geshi&quot; style=&quot;text-align: left&quot;&gt;div &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; calc&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #933;&quot;&gt;100px&lt;/span&gt; - &lt;span style=&quot;color: #933;&quot;&gt;50px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; calc&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #933;&quot;&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;100&lt;/span&gt;%&lt;/span&gt; - &lt;span style=&quot;color: #933;&quot;&gt;50px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;Both Sass and Myth compile to the same CSS:&lt;/p&gt;

&lt;div class=&quot;css geshi&quot; style=&quot;text-align: left&quot;&gt;div &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;50px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; calc&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #933;&quot;&gt;&lt;span style=&quot;color: #cc66cc;&quot;&gt;100&lt;/span&gt;%&lt;/span&gt; - &lt;span style=&quot;color: #933;&quot;&gt;50px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;But in Myth it is up to me — the developer — to figure out which way a &lt;code&gt;calc()&lt;/code&gt; will behave. I don&#039;t think the argument type (pixel value vs. percent value) should determine that. I&#039;m not sure why exactly, but this is ringing all sorts of alarm bells.&lt;/p&gt;

&lt;h2&gt;CSS Variables&lt;/h2&gt;

&lt;p&gt;Myth decided to use the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/dev.w3.org/csswg/css-variables/&#039;]);&quot;  href=&quot;http://dev.w3.org/csswg/css-variables/&quot;&gt;CSS Custom Properties&lt;/a&gt; notation for their variables:&lt;/p&gt;

&lt;div class=&quot;css geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #3333ff;&quot;&gt;:root &lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; var-&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;100px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;p &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; var&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;compiles to&lt;/p&gt;

&lt;div class=&quot;css geshi&quot; style=&quot;text-align: left&quot;&gt;p &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;100px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;There&#039;s not much of a difference comparing the example above to Sass:&lt;/p&gt;

&lt;div class=&quot;css geshi&quot; style=&quot;text-align: left&quot;&gt;$width&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;100px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;p &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; $width&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;But since we&#039;re talking about a polyfilling preprocessor, we have to take a deeper look beyond the syntax of CSS Variables. Comparing preprocessor variables to CSS Custom Properties is like comparing a Fiat 500 to a battle tank.&lt;/p&gt;

&lt;h3&gt;Source Order&lt;/h3&gt;

&lt;p&gt;Both Myth and Sass use variables like &quot;replacing static placeholders&quot;. They disagree on the declaration/usage order, though. Sass interprets the source sequentially. Every variable declaration it encounters is pushed onto map. Every variable usage looks at the map. This is what we&#039;d call &quot;source order&quot;:&lt;/p&gt;

&lt;div class=&quot;css geshi&quot; style=&quot;text-align: left&quot;&gt;$width&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;100px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;p &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; $width&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;$width&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;200px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;// yields&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; p &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;100px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;Myth, being a &quot;CSS polyfill&quot; complies with the &quot;last valid declaration&quot; character of CSS:&lt;/p&gt;

&lt;div class=&quot;css geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #3333ff;&quot;&gt;:root &lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; var-&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;100px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;p &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; var&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #3333ff;&quot;&gt;:root &lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; var-&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;200px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;// yields&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; p &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;200px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt; &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;I don&#039;t think this would be a problem in cleanly maintained source. To anyone coming from a traditional precompiler this might be a WTF-moment. But really, it&#039;s more like CSS works than how preprocessors tend to deal with things.&lt;/p&gt;

&lt;h3&gt;Mind The Cascade&lt;/h3&gt;

&lt;p&gt;You might&#039;ve noticed that the examples declared variables in the &lt;code&gt;:root&lt;/code&gt; block. That is because a CSS rule (&lt;code&gt;property: value;&lt;/code&gt;) must be declared in a block — it can&#039;t be a direct child of the document. In other words: there are no global CSS rules. That is, until you meet the cascade. If you apply &lt;code&gt;html { font-size: 20px; }&lt;/code&gt; that will also be the inherited font-size of &lt;code&gt;body&lt;/code&gt; (and any other descendant element, unless it&#039;s overwritten somewhere). CSS Variables &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/dev.w3.org/csswg/css-variables/#using-variables&#039;]);&quot;  href=&quot;http://dev.w3.org/csswg/css-variables/#using-variables&quot;&gt;follow the same rule&lt;/a&gt; and thus allows the following:&lt;/p&gt;

&lt;div class=&quot;css geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #3333ff;&quot;&gt;:root &lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; var-&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;100px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;div &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; var&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;background&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #993333;&quot;&gt;red&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;div&lt;span style=&quot;color: #6666ff;&quot;&gt;.wide&lt;/span&gt; &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; var-&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;200px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;For any &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; the width would be &lt;code&gt;100px&lt;/code&gt;, for any &lt;code&gt;&amp;lt;div class=&quot;wide&quot;&amp;gt;&lt;/code&gt; the width would be &lt;code&gt;200px&lt;/code&gt;. The cascade takes care of this for us in the browser. If we were to accomplish the same thing in a preprocessor, we would have to analyze the declaration and usage of each variable, map the graphs and fold selectors into an output like:&lt;/p&gt;

&lt;div class=&quot;css geshi&quot; style=&quot;text-align: left&quot;&gt;div &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;100px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;background&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #993333;&quot;&gt;red&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;div&lt;span style=&quot;color: #6666ff;&quot;&gt;.foo&lt;/span&gt; &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;200px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;While only annoying to implement, this generates rather ugly CSS if your variable usage gets more complex than the example. Myth doesn&#039;t do it and forces you to declare variables in &lt;code&gt;:root&lt;/code&gt; blocks. It&#039;s taking the easy way out.&lt;/p&gt;

&lt;h3&gt;Powerful API&lt;/h3&gt;

&lt;p&gt;You already know the DOM (Document Object Model). There&#039;s a similar thing for styles, the &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/dev.w3.org/csswg/cssom/&#039;]);&quot;  href=&quot;http://dev.w3.org/csswg/cssom/&quot;&gt;CSSOM&lt;/a&gt; (CSS Object Model). It gives you access to anything within your CSS. We&#039;ve had a subset of this on a DOM Element basis for years, it&#039;s the &lt;code&gt;style&lt;/code&gt; property. Of course CSS Variables are exposed through that API as well. You can easily &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/dev.w3.org/csswg/css-variables/#cssom&#039;]);&quot;  href=&quot;http://dev.w3.org/csswg/css-variables/#cssom&quot;&gt;change, add and remove variables&lt;/a&gt; at runtime. Consider the following CSS:&lt;/p&gt;

&lt;div class=&quot;css geshi&quot; style=&quot;text-align: left&quot;&gt;body &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; var-&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;100px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; var-increment&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #cc66cc;&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;div &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; var&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;and add a bit of JavaScript:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; button &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; document.&lt;span style=&quot;color: #660066;&quot;&gt;getElementById&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;make-wider&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; style &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; document.&lt;span style=&quot;color: #660066;&quot;&gt;body&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;style&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;button.&lt;span style=&quot;color: #660066;&quot;&gt;addEventListener&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;click&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; width &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; style.&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;width&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; increment &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; style.&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;increment&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; incrementedWidth &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; parseInt&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;width&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;+&lt;/span&gt; parseInt&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;increment&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&amp;quot;px&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; style.&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;width&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;,&lt;/span&gt; incrementedWidth&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;&lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/jsfiddle.net/rodneyrehm/K6Gke/&#039;]);&quot;  href=&quot;http://jsfiddle.net/rodneyrehm/K6Gke/&quot;&gt;Try the fiddle (in Firefox Nightly)&lt;/a&gt;. As you can see, CSS Variables might just change the way we work with CSS altogether. We can use them to move styling related configuration from JavaScript to CSS. We can update a single value rather than having to deal with classes, specificity and overwriting declarations all the time.&lt;/p&gt;

&lt;p&gt;CSS Variables can be optimized in a way that classes and styles can&#039;t. The rendering engine is likely maintaining a map of variable declarations and uses within the CSS. It can maintain another map referencing the affected DOM elements. It doesn&#039;t have to restyle the entire DOM tree in order to find out which nodes have changed simply because we added a class to &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt;. Using those maps, it knows &lt;em&gt;exactly what changed where&lt;/em&gt;. I&#039;m not saying this is an easy thing and will be available from the get go. I&#039;m saying that I can see this avenue being pursued by our beloved performance gurus.&lt;/p&gt;

&lt;p&gt;Anyway, Myth — in its current form — won&#039;t allow you to build upon this feature. All &lt;code&gt;var(name)&lt;/code&gt; instances are replaced at compilation. They could&#039;ve allowed that by generating output that looks a bit like this:&lt;/p&gt;

&lt;div class=&quot;css geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #3333ff;&quot;&gt;:root &lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; var-&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;100px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;div &lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #933;&quot;&gt;100px&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;:&lt;/span&gt; var&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #00AA00;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;it is not obvious if &lt;code&gt;calc()&lt;/code&gt; is executed by the browser or the preprocessor&lt;/li&gt;
&lt;li&gt;CSS Variable adhere to the cascade - Myth does not&lt;/li&gt;
&lt;li&gt;CSS Variables are dynamic - Myth kills that feature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CSS Variables aren&#039;t too far away: &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/hacks.mozilla.org/2013/12/css-variables-in-firefox-nightly/&#039;]);&quot;  href=&quot;https://hacks.mozilla.org/2013/12/css-variables-in-firefox-nightly/&quot;&gt;CSS Variables in Firefox Nightly&lt;/a&gt;. In Chrome Canary you can enable them by activating &lt;a href=&quot;chrome://flags/#enable-experimental-web-platform-features&quot;&gt;Experimental Web Platform features in about:flags&lt;/a&gt;. We&#039;ll see this feature in stable releases in early 2014.&lt;/p&gt;

&lt;p&gt;I looked into Myth because they made an interesting claim. A claim that the home page of &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.myth.io/&#039;]);&quot;  href=&quot;http://www.myth.io/&quot;&gt;Myth.io&lt;/a&gt; made me doubt. A claim I can (very much to my dissatisfaction) confirm is bollocks. I&#039;m not saying Myth is bad, but I don&#039;t think it&#039;s going to work for me.&lt;/p&gt;

&lt;p&gt;The problems with CSS Variables &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/segmentio/myth/issues/10&#039;]);&quot;  href=&quot;https://github.com/segmentio/myth/issues/10&quot;&gt;were explained in issue #10&lt;/a&gt; and pretty much ignored, except for the one thing Tab suggested. I hope they figure things out and can live up to the &quot;promise&quot;. I&#039;ll happily revisit the tool once they do.&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Mon, 23 Dec 2013 11:07:35 +0100</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/30-guid.html</guid>
    
</item>
<item>
    <title>Subliminal Learning</title>
    <link>https://blog.rodneyrehm.de/archives/29-Subliminal-Learning.html</link>
    
    <comments>https://blog.rodneyrehm.de/archives/29-Subliminal-Learning.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=29</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=29</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;Let&#039;s talk about &lt;em&gt;accidentally&lt;/em&gt; teaching something while explaining something entirely different. Conveying a message within the message. Presenting the reader with information we aren&#039;t even really covering. I didn&#039;t study psychology. I&#039;m not big in educational science, either. There may very well be an official term for the thoughts I&#039;m calling &lt;em&gt;Subliminal Learning&lt;/em&gt;. Maybe &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/translate.google.de/#la/en/Scientia%20doctrina%20inter%20lineas&#039;]);&quot;  href=&quot;http://translate.google.de/#la/en/Scientia%20doctrina%20inter%20lineas&quot;&gt;Scientia doctrina inter lineas&lt;/a&gt;. Wouldn&#039;t that be giving this line of though much more substance? Anyway, this blog post is a question, not wisdom I&#039;d like to share.&lt;/p&gt;

&lt;p&gt;I&#039;ve recently proof-read an article that contained a bit of example code. An HTML fragment that was used as the base of a tabbed panel implementation. Instead of using &lt;code&gt;style=&quot;display: none&quot;&lt;/code&gt; or &lt;code&gt;class=&quot;hidden&quot;&lt;/code&gt; or whatever, the author chose to use &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.w3.org/TR/wai-aria/states_and_properties#aria-hidden&#039;]);&quot;  href=&quot;http://www.w3.org/TR/wai-aria/states_and_properties#aria-hidden&quot;&gt;&lt;code&gt;aria-hidden=&quot;true&quot;&lt;/code&gt;&lt;/a&gt;. There was no mention of accessibility. No explanation of what that weird-looking &lt;code&gt;aria&lt;/code&gt; meant. Only the accompanying CSS &lt;code&gt;[aria-hidden=&quot;true&quot;] { display: none; }&lt;/code&gt; served as a hint to what this was supposed to accomplish. That was the &lt;em&gt;only&lt;/em&gt; use of &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.w3.org/TR/wai-aria/&#039;]);&quot;  href=&quot;http://www.w3.org/TR/wai-aria/&quot;&gt;WAI ARIA&lt;/a&gt; in that article. But it was enough to get me interested.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;To illustrate my point, have a look at this tab panel example using ARIA roles:&lt;/p&gt;

&lt;div class=&quot;xml geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tabgroup&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;ul&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;role&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tablist&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;li&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tab1&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;aria-controls&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;panel1&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;role&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tab&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;active&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Tab 1&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/li&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;li&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tab2&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;aria-controls&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;panel2&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;role&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tab&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Tab 2&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/li&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/ul&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;panel1&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;aria-labeledby&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tab1&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;role&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tabpanel&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; … &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/div&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;panel2&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;aria-labeledby&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tab2&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;role&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tabpanel&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;aria-hidden&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; … &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/div&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/div&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;Now compare that to markup we&#039;ve come to expect to see in examples on the web:&lt;/p&gt;

&lt;div class=&quot;xml geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tabgroup&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;ul&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tablist&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;li&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tab1&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tab active&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Tab 1&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/li&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;li&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tab2&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tab&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;Tab 2&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/li&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/ul&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;panel1&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;data-for&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tab1&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tabpanel&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; … &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/div&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;panel2&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;data-for&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tab2&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;tabpanel hidden&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; … &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/div&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/div&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;Until today I thought of aria as something you &lt;em&gt;add&lt;/em&gt; to your markup (and subsequently never really looked into it). Only now do I realize that you can actually use this &lt;em&gt;in place of&lt;/em&gt; other (less semantic) things you did.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Earlier I said I was going to ask a question, so here it is: &lt;strong&gt;Would I know more about WAI ARIA, had I seen it used in &quot;everyday code examples&quot; rather than only in articles covering accessibility?&lt;/strong&gt; I think I would.&lt;/p&gt;

&lt;p&gt;I would have - most probably - not looked up WAI ARIA at first. In fact, I would&#039;ve probably just started using it - the way the examples taught me - without giving it a closer look. After all, it was quite a number of years &lt;em&gt;after&lt;/em&gt; I started with web development, that I had my first look at an official specification document. The thing is, we learn a couple of things and we infer from there. (and by &quot;we&quot; I mean &quot;me&quot;)&lt;/p&gt;

&lt;p&gt;We tend to search for answers to the problem at hand. The above example shows a tab panel, so I&#039;d likely be looking for something explaining how &lt;em&gt;that&lt;/em&gt; works. All that &lt;code&gt;aria&lt;/code&gt; stuff in there is just something I would pick up along the way. Possibly using it as a base to start investigations from the next time &#039;round. It&#039;s clearly not necessary information to build a tab panel - but it&#039;s important if you want to get it &lt;em&gt;right&lt;/em&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The same holds true for pretty much everything else we know. How to write easily testable code is left up to articles covering the topic of testing. The problem is, people have to &lt;em&gt;know&lt;/em&gt; that testing/testability is a thing to go looking for information on it. They&#039;re not - accidentally or consciously - nudged in the right direction. (&quot;right direction&quot;, whatever we think that is…)&lt;/p&gt;

&lt;p&gt;I remember &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/christianheilmann.com/&#039;]);&quot;  href=&quot;http://christianheilmann.com/&quot;&gt;Chris Heilmann&lt;/a&gt; explaining to me the problem he saw with the efforts to propagate HTML5 throughout the software industry (yep, the &quot;enterprise&quot; thingie). We are speaking at conferences &lt;em&gt;for people interested in the web&lt;/em&gt;. We are writing articles &lt;em&gt;for people interested in the web&lt;/em&gt;. Unless you&#039;re interested in the web, you&#039;re not going to attend our conferences, you&#039;re not going to read our blogs. We are - quite literally - &lt;del&gt;preaching&lt;/del&gt;&lt;ins&gt;living&lt;/ins&gt; in an echo chamber. We reach the people we&#039;ve always reached, but not those that could actually benefit the most.&lt;/p&gt;

&lt;p&gt;I think we&#039;re experiencing a similar problem when writing about ES6 and calling it &quot;ECMAScript6: The Future of JavaScript&quot;. Unless we start using &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap&#039;]);&quot;  href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap&quot;&gt;&lt;code&gt;WeakMap&lt;/code&gt;&lt;/a&gt; in code examples that are &lt;em&gt;not&lt;/em&gt; about ES6, the majority won&#039;t care. Unless we start using role attributes in articles about UI Components, the majority won&#039;t care.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I handed this post to a couple of people before publishing it. I got responses like »I had no idea that ARIA could be useful for more than accessibility alone« and »Now I&#039;m using ARIA everywhere, at least the role attribute«. Doesn&#039;t that kind of prove my point?&lt;/p&gt;

&lt;p&gt;But is this really the problem I make it out to be? I don&#039;t know. Can we do Better? We can certainly try!&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Fri, 20 Dec 2013 20:47:58 +0100</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/29-guid.html</guid>
    
</item>
<item>
    <title>Running Keynote With 3 Monitors</title>
    <link>https://blog.rodneyrehm.de/archives/28-Running-Keynote-With-3-Monitors.html</link>
    
    <comments>https://blog.rodneyrehm.de/archives/28-Running-Keynote-With-3-Monitors.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=28</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=28</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;I&#039;ve recently given a presentation sitting on a couch on stage, about 5m away from my laptop. I needed a third display to show Keynote&#039;s presenter notes at a different location without using any cables. My iPad turned out to be a perfect fit. (Description for Mac OS X Mountain Lion.)&lt;/p&gt;

&lt;div class=&quot;serendipity_imageComment_center&quot; style=&quot;width: 800px&quot;&gt;&lt;div class=&quot;serendipity_imageComment_img&quot;&gt;&lt;!-- s9ymdb:17 --&gt;&lt;img class=&quot;serendipity_image_center&quot; width=&quot;800&quot; height=&quot;600&quot;  src=&quot;https://blog.rodneyrehm.de/uploads/multi-monitor/multi-mon-0.jpg&quot;  alt=&quot;Keynote showing presentation notes on 2 displays&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;serendipity_imageComment_txt&quot;&gt;Keynote showing presentation notes on 2 displays&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;Using The iPad As An External Display&lt;/h2&gt;

&lt;p&gt;I already had &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/itunes.apple.com/us/app/iscreen/id379944104&#039;]);&quot;  href=&quot;https://itunes.apple.com/us/app/iscreen/id379944104&quot;&gt;iScreen&lt;/a&gt; installed. This 5$ app and the accompanying system preference plugin for the mac make the iPad show up as an external display in your &lt;em&gt;Display&lt;/em&gt; System Preferences.&lt;/p&gt;

&lt;p&gt;The connection works via WiFi. To be on the safe side, I created a computer to computer network (ad-hoc network) using &lt;em&gt;WiFi MenuIcon&lt;/em&gt; &gt; &lt;em&gt;Create Network&lt;/em&gt; and made my iPad join that WiFi network. If you use a public network, you may get &lt;em&gt;slow connection&lt;/em&gt; warnings in iScreen.&lt;/p&gt;

&lt;h2&gt;Mirroring Multiple External Displays&lt;/h2&gt;

&lt;p&gt;The Display System Preference has a checkbox to &lt;em&gt;Mirror Displays&lt;/em&gt;. This option works well for 2 displays, but yields strange results for more devices. Also you don&#039;t want to mirror all of them, but rather mirror only two and have the third display extend the desktop. Once you&#039;ve successfully connected the iPad with iScreen, your Display System Preferences look like this&lt;/p&gt;

&lt;div class=&quot;serendipity_imageComment_center&quot; style=&quot;width: 782px&quot;&gt;&lt;div class=&quot;serendipity_imageComment_img&quot;&gt;&lt;!-- s9ymdb:18 --&gt;&lt;img class=&quot;serendipity_image_center&quot; width=&quot;782&quot; height=&quot;638&quot;  src=&quot;https://blog.rodneyrehm.de/uploads/multi-monitor/multi-mon-1.png&quot;  alt=&quot;Display System Preferences with three monitors&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;serendipity_imageComment_txt&quot;&gt;Display System Preferences with three monitors&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Make sure the projector is the primary display by dragging the white rectangle to the appropriate monitor. Hold the &lt;key&gt;alt&lt;/key&gt; key while dragging the iPad display onto your laptop display.&lt;/p&gt;

&lt;div class=&quot;serendipity_imageComment_center&quot; style=&quot;width: 782px&quot;&gt;&lt;div class=&quot;serendipity_imageComment_img&quot;&gt;&lt;!-- s9ymdb:19 --&gt;&lt;img class=&quot;serendipity_image_center&quot; width=&quot;782&quot; height=&quot;638&quot;  src=&quot;https://blog.rodneyrehm.de/uploads/multi-monitor/multi-mon-2.png&quot;  alt=&quot;Display System Preferences while synchronizing 2 of 3 monitors&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;serendipity_imageComment_txt&quot;&gt;Display System Preferences while synchronizing 2 of 3 monitors&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You&#039;ve just managed to synchronize 2 out of three displays. Virtually you now have two screens, where one is shown on one display and the other is shown own two displays.&lt;/p&gt;

&lt;h2&gt;Keynote Presenter Display&lt;/h2&gt;

&lt;p&gt;For some reason this trick only works when the presentation is displayed on the main monitor and the presenter information is shown on the &lt;em&gt;alternate display&lt;/em&gt;. We already made that happen by dragging the white rectangle to the projector in the Display System Preferences. In Keynote you now need to enable the &quot;use alternate display to view presenter information&quot; checkbox:&lt;/p&gt;

&lt;div class=&quot;serendipity_imageComment_center&quot; style=&quot;width: 674px&quot;&gt;&lt;div class=&quot;serendipity_imageComment_img&quot;&gt;&lt;!-- s9ymdb:20 --&gt;&lt;img class=&quot;serendipity_image_center&quot; width=&quot;674&quot; height=&quot;529&quot;  src=&quot;https://blog.rodneyrehm.de/uploads/multi-monitor/multi-mon-3.png&quot;  alt=&quot;Keynote presenter settings&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;serendipity_imageComment_txt&quot;&gt;Keynote presenter settings&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And that&#039;s it. Once you play the presentation you should see the slides on your external display (projector) and the presenter notes on your laptop and the iPad. Since it runs on WiFi, you can take the iPad to anywhere you want.&lt;/p&gt;

&lt;h2&gt;TL;DR&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;use &lt;key&gt;alt&lt;/key&gt; key while dropping one monitor onto the other in Display System Preferences to synchronize them&lt;/li&gt;
&lt;li&gt;make sure Keynote is showing the presentation on the primary monitor and the synchronized displays run as secondary monitors&lt;/li&gt;
&lt;/ul&gt;
 
    </content:encoded>

    <pubDate>Mon, 16 Dec 2013 13:15:25 +0100</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/28-guid.html</guid>
    
</item>
<item>
    <title>Dialog for Unsupported Browsers</title>
    <link>https://blog.rodneyrehm.de/archives/27-Dialog-for-Unsupported-Browsers.html</link>
            <category>javascript</category>
    
    <comments>https://blog.rodneyrehm.de/archives/27-Dialog-for-Unsupported-Browsers.html#comments</comments>
    <wfw:comment>https://blog.rodneyrehm.de/wfwcomment.php?cid=27</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>https://blog.rodneyrehm.de/rss.php?version=2.0&amp;type=comments&amp;cid=27</wfw:commentRss>
    

    <author>nospam@example.com (Rodney Rehm)</author>
    <content:encoded>
    &lt;p&gt;There is no greater failure than showing a white screen. If an application can&#039;t run in a given environment (&quot;old&quot; browsers) telling users might not make them upgrade right away. But compared to a blank page they&#039;ll actually know what&#039;s going on. Here&#039;s a (debatable) method to achieve that. My day job is comprised of building web applications. Without bothering you with the details, our lowest end browsers are Internet Explorer 9 and Android 4.0.x Stock Browser. We chose to not support IE8 at all. This decision allowed us to go with &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/kangax.github.io/es5-compat-table/&#039;]);&quot;  href=&quot;http://kangax.github.io/es5-compat-table/&quot;&gt;ES5&lt;/a&gt;, &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/developer.mozilla.org/en-US/docs/Web/SVG&#039;]);&quot;  href=&quot;https://developer.mozilla.org/en-US/docs/Web/SVG&quot;&gt;SVG&lt;/a&gt;, &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/developer.mozilla.org/en-US/docs/Web/CSS/transform&#039;]);&quot;  href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/transform&quot;&gt;CSS Transform&lt;/a&gt; etc. without having to polyfill anything. On top of using these technologies, we created &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/backbonejs.org/&#039;]);&quot;  href=&quot;http://backbonejs.org/&quot;&gt;BackboneJS&lt;/a&gt; applications which made our HTML pretty much look like &lt;code&gt;&amp;lt;body&amp;gt;&amp;lt;/body&amp;gt;&lt;/code&gt;. There are reasons we don&#039;t render any HTML on the &quot;server&quot;, but I&#039;m not at liberty to discuss this any further at this point.&lt;/p&gt;

&lt;p&gt;Of course all this lead to a blank blank page in old browsers. If that wasn&#039;t enough, the browsers would throw a myriad of JavaScript errors because it couldn&#039;t parse and or execute anything we shoved down their throats.&lt;/p&gt;

&lt;p&gt;The Management™ agreed with the developer&#039;s pride: We needed some sort of &quot;beautiful&quot; masquerade for this.&lt;/p&gt;

&lt;h2&gt;The Or Else Approach&lt;/h2&gt;

&lt;p&gt;Our first draft looked a bit like the following snippet. We inlined the content targeting old browsers into our primary HTML files and had JS overwrite the content if necessary. To prevent old browsers from parsing and executing our JavaScript we only injected it if we were sure the browser could run it.&lt;/p&gt;

&lt;div class=&quot;xml geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;head&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;rel&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;href&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;style.css&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/head&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;body&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;script&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;javascript/template&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;old-browser-html&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;p&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Your Browser sucks!&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/p&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/script&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;script&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;type&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;javascript/template&amp;quot;&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;id&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;modern-browser-js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;script&lt;/span&gt; &lt;span style=&quot;color: #000066;&quot;&gt;src&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;main.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/scr-ipt&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/script&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;script&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; if (oldBrowser) {&lt;br /&gt;&amp;#160; &amp;#160; // remove any existing CSS&lt;br /&gt;&amp;#160; &amp;#160; var links = document.getElementsByTagName(&#039;link&#039;);&lt;br /&gt;&amp;#160; &amp;#160; while (links.length) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; links[0].parentNode.removeChild(links[0]);&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; &lt;br /&gt;&amp;#160; &amp;#160; // inject old browser dialog&lt;br /&gt;&amp;#160; &amp;#160; var html = document.getElementById(&amp;quot;old-browser-html&amp;quot;);&lt;br /&gt;&amp;#160; &amp;#160; document.body.innerHTML = html.innerHTML;&lt;br /&gt;&amp;#160; } else {&lt;br /&gt;&amp;#160; &amp;#160; // load primary JS&lt;br /&gt;&amp;#160; &amp;#160; var script = document.getElementById(&#039;modern-browser-js&#039;);&lt;br /&gt;&amp;#160; &amp;#160; script = script.innerHTML.replace(/&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;&lt;/span&gt;\/scr-ipt&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;/g, &#039;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/script&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&#039;);&lt;br /&gt;&amp;#160; &amp;#160; document.body.insertAdjacentHTML(&amp;quot;beforeend&amp;quot;, script);&lt;br /&gt;&amp;#160; }&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/script&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/body&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;I have cut down the document to the core ingredients and even omitted how we determine if &lt;code&gt;oldBrowser&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; for brevety sake. We&#039;re using the &lt;em&gt;script template&lt;/em&gt; method (&lt;code&gt;&amp;lt;script type=&quot;javascript/template&quot;&amp;gt;&lt;/code&gt;) to carry HTML fragments in our document that are not parsed as HTML, CSS or JavaScript. Note that within such a script template we had to &quot;tweak&quot; the closing script tags from &lt;code&gt;&amp;lt;/script&amp;gt;&lt;/code&gt; to &lt;code&gt;&amp;lt;/scr-ipt&amp;gt;&lt;/code&gt; in order to have the stuff parsed properly.&lt;/p&gt;

&lt;p&gt;In case we are dealing with IE8 (&lt;code&gt;oldBrowser = true&lt;/code&gt;), we have to remove any stylesheets that the document references itself. We then simply replace the document&#039;s &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; with the content of the template for old browsers.&lt;/p&gt;

&lt;p&gt;In case we are dealing with a modern browser, we have to kick off loading the JavaScript. Because we were using &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/github.com/yeoman/grunt-usemin&#039;]);&quot;  href=&quot;https://github.com/yeoman/grunt-usemin&quot;&gt;grunt-usemin&lt;/a&gt; the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; couldn&#039;t just be added to the DOM like you normally would:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; script &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; document.&lt;span style=&quot;color: #660066;&quot;&gt;createElement&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;script&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;script.&lt;span style=&quot;color: #660066;&quot;&gt;src&lt;/span&gt; &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;main.js&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;document.&lt;span style=&quot;color: #660066;&quot;&gt;head&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;appendChild&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;script&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;While this technique worked in the beginning, it has always suffered a couple of problemes and failed us completely in the end.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The HTML for old browsers is &lt;em&gt;always&lt;/em&gt; transmitted to the client, although it is almost never rendered. Considering that our HTML is never cached, this seemed like a waste.&lt;/li&gt;
&lt;li&gt;The JavaScript couldn&#039;t be identified and loaded by the pre parser - which we could&#039;ve &quot;fixed&quot; in Chrome using &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.chromium.org/spdy/link-headers-and-server-hint/link-rel-subresource&#039;]);&quot;  href=&quot;http://www.chromium.org/spdy/link-headers-and-server-hint/link-rel-subresource&quot;&gt;&lt;code&gt;&amp;lt;link rel=&quot;subresource&quot; href=&quot;script.js&quot;&amp;gt;&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The fact that we had to rewrite the closing script tag (to &lt;code&gt;&amp;lt;/scr-ipt&amp;gt;&lt;/code&gt;) never made anyone smile&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The approach really fell apart once we added inline &lt;code&gt;&amp;lt;svg&amp;gt;&lt;/code&gt; (with more &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;s for animations). We were back to the blank page we saw without all this fuss.&lt;/p&gt;

&lt;h2&gt;The Unless Approach&lt;/h2&gt;

&lt;p&gt;We were getting close to the &lt;em&gt;release date&lt;/em&gt; (In fact we were already 3 days past delivery, but you know how that works). I was handed this bug. I had no time (4 hours till I&#039;d leave for &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/fronteers.nl/congres/2013&#039;]);&quot;  href=&quot;http://fronteers.nl/congres/2013&quot;&gt;Fronteers&lt;/a&gt; and not return in time for another round of bug fixing).&lt;/p&gt;

&lt;p&gt;Lanyrd&#039;s mobile site uses the following trick to conditionally load scripts:&lt;/p&gt;

&lt;div class=&quot;xml geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;script&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;preventScript &lt;span style=&quot;color: #ddbb00;&quot;&gt;&amp;amp;&amp;amp; document.write(&amp;quot;&amp;lt;!&amp;quot;+&amp;quot;--&amp;quot;)&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ddbb00;&quot;&gt; &amp;#160;&amp;lt;script src=&amp;quot;somes-script.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #ddbb00;&quot;&gt;&amp;lt;!----&amp;gt;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;Which works fine if the content you&#039;re trying to escape doesn&#039;t contain any HTML comments. My content did, so that trick wasn&#039;t going to fly for me. But I remembered reading about a hack that allowed JavaScript to take over a document&#039;s content before the browser&#039;s parser had a chance to work its magic -  &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.mobify.com/mobifyjs/v2/docs/&#039;]);&quot;  href=&quot;http://www.mobify.com/mobifyjs/v2/docs/&quot;&gt;MobifyJS&lt;/a&gt;. They inject a &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/developer.mozilla.org/en-US/docs/Web/HTML/Element/plaintext&#039;]);&quot;  href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/plaintext&quot;&gt;&lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt;&lt;/a&gt; element, by which the parser exits HTML mode and simply treats everything that follows as &lt;em&gt;plain text content&lt;/em&gt; of the &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; element.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; element is deprecated since &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/www.w3.org/MarkUp/html-spec/&#039;]);&quot;  href=&quot;http://www.w3.org/MarkUp/html-spec/&quot;&gt;HTML2&lt;/a&gt; - which became an IETF standard in 1995. MDN clearly marks this element as obsolete, yet &lt;a onclick=&quot;_gaq.push([&#039;_trackPageview&#039;, &#039;/extlink/hacks.mozilla.org/2013/03/capturing-improving-performance-of-the-adaptive-web/&#039;]);&quot;  href=&quot;https://hacks.mozilla.org/2013/03/capturing-improving-performance-of-the-adaptive-web/&quot;&gt;MozHacks (implicitly) promotes&lt;/a&gt; the use of &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; as late as March 2013 - nearly two decades after its demise.&lt;/p&gt;

&lt;p&gt;After testing the support of &lt;code&gt;&amp;lt;plaintext&amp;gt;&lt;/code&gt; on the various browsers and devices available to me, I decided to go forward with using it. My final &lt;em&gt;run the app or GTFO&lt;/em&gt; hack looks simple enough in the document:&lt;/p&gt;

&lt;div class=&quot;xml geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;body&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;script&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; if (oldBrowser) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; document.write(&#039;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;scr&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&#039;+&#039;&lt;/span&gt;ipt &lt;span style=&quot;color: #000066;&quot;&gt;src&lt;/span&gt;=&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;quot;old-browser-dialog.js&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/scr&lt;/span&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&#039;+&#039;&lt;/span&gt;ipt&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&#039;);&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/script&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #808080; font-style: italic;&quot;&gt;&amp;lt;!-- actual content --&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;lt;/body&lt;span style=&quot;color: #000000; font-weight: bold;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;and the &lt;code&gt;old-browser-dialog.js&lt;/code&gt; looks a little something like this:&lt;/p&gt;

&lt;div class=&quot;javascript geshi&quot; style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; html &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;old-browser-css.css&amp;quot;&amp;gt;&#039;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #339933;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;&amp;lt;p&amp;gt;Your Browser sucks!&amp;lt;/p&amp;gt;&#039;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// clean existing styles&lt;/span&gt;&lt;br /&gt;&amp;#160; removeElements&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;link&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; removeElements&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;style&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// add old browser dialog&lt;/span&gt;&lt;br /&gt;&amp;#160; document.&lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;write&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;html&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #006600; font-style: italic;&quot;&gt;// prevent document&#039;s content from being evaluated&lt;/span&gt;&lt;br /&gt;&amp;#160; document.&lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;write&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #3366CC;&quot;&gt;&#039;&amp;lt;plaintext style=&amp;quot;display: none&amp;quot;&amp;gt;&#039;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;function&lt;/span&gt; removeElements&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;tagName&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #003366; font-weight: bold;&quot;&gt;var&lt;/span&gt; nodes &lt;span style=&quot;color: #339933;&quot;&gt;=&lt;/span&gt; document.&lt;span style=&quot;color: #660066;&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;tagName&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #000066; font-weight: bold;&quot;&gt;while&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;nodes.&lt;span style=&quot;color: #660066;&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; nodes&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#93;&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;parentNode&lt;/span&gt;.&lt;span style=&quot;color: #660066;&quot;&gt;removeChild&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;nodes&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span style=&quot;color: #CC0000;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;br /&gt;&amp;#160; &amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&amp;#160; &lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span style=&quot;color: #009900;&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span style=&quot;color: #339933;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;

&lt;p&gt;That solved all the problems we had.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Presenting old browsers an update dialog.&lt;/li&gt;
&lt;li&gt;Preventing them from executing our JavaScript.&lt;/li&gt;
&lt;li&gt;Being &lt;strong&gt;unobtrusive&lt;/strong&gt; to the rest of the document&#039;s content.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once I committed this to our SVN, I called my team to my screen and explained that I would shoot anyone that &lt;em&gt;ever&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Uses &lt;code&gt;document.write()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Uses deprecated HTML Elements&lt;/li&gt;
&lt;li&gt;Question my ability to break the web&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(yeah yeah, the irony, I know…)&lt;/p&gt;
 
    </content:encoded>

    <pubDate>Tue, 08 Oct 2013 18:04:05 +0200</pubDate>
    <guid isPermaLink="false">https://blog.rodneyrehm.de/archives/27-guid.html</guid>
    
</item>

</channel>
</rss>
