{"database": "24ways", "table": "articles", "is_view": false, "human_description_en": "where author_slug = \"richthornett\", topic = \"process\" and year = 2011", "rows": [[286, "Defending the Perimeter Against Web Widgets", "On July 14, 1789, citizens of Paris stormed the Bastille, igniting a revolution that toppled the French monarchy. On July 14 of this year, there was a less dramatic (though more tweeted) takedown: The Deck network, which delivers advertising to some of the most popular web design and culture destinations, was down for about thirty minutes. During this period, most partner sites running ads from The Deck could not be viewed as result.\n\nA few partners were unaffected (aside from not having an ad to display). Fortunately, Dribbble, was one of them. In this article, I\u2019ll discuss outages like this and how to defend against them. But first, a few qualifiers: The Deck has been rock solid \u2013 this is the only downtime we\u2019ve witnessed since joining in June. More importantly, the issues in play are applicable to any web widget you might add to your site to display third-party content.\n\nDown and out\n\nYour defense is only as good as its weakest link. Web pages are filled with links, some of which threaten the ability of your page to load quickly and correctly. If you want your site to work when external resources fail, you need to identify the weak links on your site. In this article, we\u2019ll talk about web widgets as a point of failure and defensive JavaScript techniques for handling them.\n\nWidgets 101\n\nImagine a widget that prints out a Pun of the Day on your site. A simple technique for both widget provider and consumer is for the provider to expose a URL:\n\nhttp://widgetjonesdiary.com/punoftheday.js\n\nwhich returns a JavaScript file like this:\n\ndocument.write(\"<h2>The Pun of the Day</h2><p>Where do frogs go for beers after work? Hoppy hour!</p>\");\n\nThe call to document.write() injects the string passed into the document where it is called. So to display the widget on your page, simply add an external script tag where you want it to appear:\n\n<div class=\"punoftheday\">\n  <script src=\"http://widgetjonesdiary.com/punoftheday.js\"></script>\n  <!-- Content appears here as output of script above -->\n</div>\n\nThis approach is incredibly easy for both provider and consumer. But there are implications\u2026\n\ndocument.write()\u2026 or wrong?\n\nAs in the example above, scripts may perform a document.write() to inject HTML. Page rendering halts while a script is processed so any output can be inlined into the document. Therefore, page rendering speed depends on how fast the script returns the data. If an external JavaScript widget hangs, so does the page content that follows. It was this scenario that briefly stalled partner sites of The Deck last summer.\n\nThe elegant solution\n\nTo make our web widget more robust, calls to document.write() should be avoided. This can be achieved with a technique called JSONP (AKA JSON with padding). In our example, instead of writing inline with document.write(), a JSONP script passes content to a callback function:\n\npublishPun(\"<h2>Pun of the Day</h2><p>Where do frogs go for beers after work? Hoppy hour!</p>\");\n\nThen, it\u2019s up to the widget consumer to implement a callback function responsible for displaying the content. Here\u2019s a simple example where our callback uses jQuery to write the content into a target <div>:\n\n<!-- Where widget content should appear -->\n<div class=\"punoftheday\"></div>\n\n\u2026\n\n\n<br />\nfunction publishPun(content) {\n  $(&#8216;.punoftheday&#8217;).html(content); // Writes content display location<br />\n}<br />\n\n\n\n\nView Example 1\n\nEven if the widget content appears at the top of the page, our script can be included at the bottom so it\u2019s non-blocking: a slow response leaves page rendering unaffected. It simply invokes the callback which, in turn, writes the widget content to its display destination.\n\nThe hack\n\nBut what to do if your provider doesn\u2019t support JSONP? This was our case with The Deck. Returning to our example, I\u2019m reminded of computer scientist David Wheeler\u2019s statement, \u201cAll problems in computer science can be solved by another level of indirection\u2026 Except for the problem of too many layers of indirection.\u201d\n\nIn our case, the indirection is to move the widget content into position after writing it to the page. This allows us to place the widget <script> tag at the bottom of the page so rendering won\u2019t be blocked, but still display the widget in the target. The strategy:\n\n\n\tLoad widget content into a hidden <div> at the bottom of the page.\n\tMove the loaded content from the hidden <div> to its display location.\n\n\nand the code:\n\n<!-- Where widget content should appear -->\n<div class=\"punoftheday\"></div>\n\n\u2026\n\n\n\n  \n  \n\n\n\n<br />\n$(&#8216;.punoftheday&#8217;).append($(&#8216;.loading-dock&#8217;).children(&#8216;:gt(0)&#8217;));<br />\n\nView Example 2\n\nAfter the external punoftheday.js script has processed, the rendered HTML will look as follows:\n\n<div class=\"loading-dock hidden\">\n  <script src=\"http://widgetjonesdiary.com/punoftheday.js\"></script>\n  <h2>Pun of the Day</h2>\n  <p>Where do frogs go for beers after work? Hoppy hour!</p>\n</div>\n\nThe \u2018loading-dock\u2019 <div> now includes the widget content, albeit hidden from view (if we\u2019ve styled the \u2018hidden\u2019 class with display: none). There\u2019s just one more step: move the content to its display destination. This line of jQuery (from above) does the trick:\n\n$('.punoftheday').append($('.loading-dock').children(':gt(0)'));\n\nThis selects all child elements in the \u2018loading-doc\u2019 <div> except the first \u2013 the widget <script> tag which generated it \u2013 and moves it to the display destination. Worth noting is the :gt(0) jQuery selector extension, which allows us to exclude the first (in a 0-based array) child element \u2013 the widget <script> tag \u2013 from selection.\n\nSince all of this happens at the bottom of the page, just before the </body> tag, no rendering has to wait on the external widget script. The only thing that fails if our widget hangs is\u2026 the widget itself. Our weakest link has been strengthened and so has our site. DE-FENSE!", "2011", "Rich Thornett", "richthornett", "2011-12-06T00:00:00+00:00", "https://24ways.org/2011/defending-the-perimeter-against-web-widgets/", "process"]], "truncated": false, "table_rows_count": 336, "filtered_table_rows_count": 1, "expanded_columns": [], "expandable_columns": [], "columns": ["rowid", "title", "contents", "year", "author", "author_slug", "published", "url", "topic"], "primary_keys": [], "units": {}, "query": {"sql": "select rowid, * from articles where \"author_slug\" = :p0 and \"topic\" = :p1 and \"year\" = :p2 order by rowid limit 101", "params": {"p0": "richthornett", "p1": "process", "p2": "2011"}}, "facet_results": {}, "suggested_facets": [], "next": null, "next_url": null, "query_ms": 16.016721725463867}