<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>Hi! I’m Joe, Lead Mobile Engineer at Vimeo. Reusable Bits is where I post random bits and snippets I’ve created that I find cool or useful and think you might as well.

Check out my projects.


  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-20822197-2']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement(‘script’); ga.type = ‘text/javascript’; ga.async = true;
    ga.src = (‘https:’ == document.location.protocol ? ‘https://ssl’ : ‘http://www’) + ‘.google-analytics.com/ga.js’;
    var s = document.getElementsByTagName(‘script’)[0]; s.parentNode.insertBefore(ga, s);
  })();</description><title>Reusable Bits</title><generator>Tumblr (3.0; @reusablebits)</generator><link>http://reusablebits.com/</link><item><title>Embedinator</title><description>&lt;a href="https://github.com/josephschmitt/Embedinator"&gt;Embedinator&lt;/a&gt;: &lt;p&gt;&lt;img src="http://f.cl.ly/items/1v2f0I3Q2N1J11381k3Q/Screen%20Shot%202011-08-04%20at%202.25.49%20PM.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;One of the first decisions I made after getting my MacBook Air was that I would try running it without Adobe’s Flash player installed for a while and see how it would do. After all, Apple wasn’t even installing Flash on its computers anymore, so the open web must be doing pretty well, right? I ran with this setup for a couple of reasons other than Apple’s refusal to install it on my system. First, I’m a fan of performance and all evidence points to Flash taking performance out back, putting a shotgun to its head, and going all Old Yeller on it’s ass (err, head). Second, I was curious to see how much of the web had moved over to using HTML5-compatible video standards now that the iPad had been out for almost 18 months.&lt;/p&gt;

&lt;p&gt;The experiment worked pretty well, actually. With Vimeo videos, since we &lt;a href="http://vimeo.com/blog:334"&gt;released the Universal Embed Code&lt;/a&gt; and &lt;a href="http://vimeo.com/blog:391"&gt;Desktop HTML5 Player&lt;/a&gt; last year, the vast majority of new videos played fine. YouTube, however, was a different story. They also have an &lt;a href="http://www.youtube.com/html5"&gt;embeddable HTML5 player&lt;/a&gt;, but they’re certainly in no rush to promote it, so most YouTube embeds are of the Flash &lt;object&gt; embed variety. To get around this, there’s a neat Safari extension called &lt;a href="http://www.verticalforest.com/youtube5-extension/"&gt;YouTube5&lt;/a&gt; that replaces YouTube Flash video players with a nice, simple HTML5 player that plays great on the desktop. Life was good.&lt;/p&gt;

&lt;p&gt;Then, a couple of days ago, YouTube changed something on their end and inadvertently (or not so inadvertently) broke YouTube5. I’m sure the extension author will get around to fixing the extension at some point, but what’s to stop it from breaking again in the future? There has to be a better way.&lt;/p&gt;

&lt;p&gt;As it turns out there &lt;em&gt;is&lt;/em&gt; a better way, and I actually wrote it myself when we originally announced our Universal Embed player at Vimeo. When the Universal Embed first came out, we had deal with the fact that while all &lt;em&gt;future&lt;/em&gt; embedded videos would be able to display HTML5 or Flash video players, we still had millions and millions of embedded videos that were embedded the old-fashioned way with Flash (which is true to this day). The solution was a snippet of JavaScript I wrote that would search the page for any old Flash embed code, grab all of the important information we needed from it, and replace it with the updated Universal Embed. The original intention was for site authors to use on their own websites, but there’s no reason this couldn’t be (quite easily) turned into a browser extension.&lt;/p&gt;

&lt;p&gt;So, without further ado, I give you the &lt;a href="https://github.com/josephschmitt/Embedinator"&gt;Embedinator&lt;/a&gt;. It’ll scan the page for embeds and update them where necessary. By default it automatically runs every time you load a page in your browser, but you can turn that off and run it manually by clicking on the button in the toolbar. It of course supports Vimeo videos, but I’ve also added support for our friends over at YouTube, using their own iframe embed player to replace all of their old embeds. As well as supporting YouTube, I’ve structured the extension so that it’s easy to add more services, so if you think of any other video players that have an HTML5-compatible version, feel free to contact me with the details and I’ll try and add support for it.&lt;/p&gt;

&lt;p&gt;Like all of my projects here on Reusable Bits, Embedinator is open source and &lt;a href="https://github.com/josephschmitt/Embedinator"&gt;available on GitHub&lt;/a&gt;. Feel free to check out the source, give suggestions, or fix any bugs for me :-). If you’re just interested in downloading and installing the extension itself, you can find it below.&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://s3.amazonaws.com/reusebits/embedinator/Embedinator.safariextz"&gt;Download Embedinator for Safari&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Latest version (Embedinator 1.1) works with (most) videos on YouTube.com. Unfortunately, since it’s using embed code, any video whose settings don’t allow the video to be embedded won’t be playable. Such is life.&lt;/p&gt;</description><link>http://reusablebits.com/post/8479172066</link><guid>http://reusablebits.com/post/8479172066</guid><pubDate>Thu, 04 Aug 2011 19:43:02 -0400</pubDate><dc:creator>josephschmitt</dc:creator></item><item><title>Drawing Resolution Less-Dependent Graphics</title><description>&lt;p&gt;&lt;img src="http://f.cl.ly/items/441F2L323s3O1q1g273k/resolution.jpg" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;One of the great recent additions to modern browsers is the &lt;a href="https://developer.mozilla.org/en/html/canvas"&gt;&lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;&lt;/a&gt; element. The &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element enables a whole new world of client-side scripting awesomeness by allowing you to draw graphics into an HTML element via JavaScript.&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s awesome!&lt;/p&gt;

&lt;p&gt;However, a popular misconception&lt;sup id="fnref:p8141645542-1"&gt;&lt;a href="#fn:p8141645542-1" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt; exists with the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element: &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; graphics are not vector graphics, they&amp;#8217;re &lt;a href="http://en.wikipedia.org/wiki/Raster_graphics"&gt;raster&lt;/a&gt;. What does this mean? It means if you&amp;#8217;re viewing your beautiful &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; artwork on a &lt;a href="http://www.apple.com/ios/"&gt;device&lt;/a&gt; that &lt;a href="http://www.android.com/"&gt;supports&lt;/a&gt; zooming, once you zoom past 100%, your artwork will get pixelated.&lt;/p&gt;

&lt;p&gt;That sucks!&lt;/p&gt;

&lt;p&gt;So, how do we solve this? As it so happens, this issue was &lt;a href="http://www.webkit.org/blog/55/high-dpi-web-sites/"&gt;solved several years ago&lt;/a&gt; before these zoomable devices were even on the market by none other than the Webkit team:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The img element already supports specifying explicit sizes, and so today you can specify a width and height and if an image is larger it will be downscaled. In a high DPI system where 1 CSS pixel&amp;#160;!= 1 device pixel, more detail can then be rendered.&lt;/p&gt;
  
  &lt;p&gt;In other words how you scale an image is based off comparing &lt;em&gt;device pixels&lt;/em&gt; and not CSS pixels. For example, if you have a zoom factor of 2, an img tag that specifies a width and height of 100 CSS pixels, and an image whose intrinsic size is 200×200
  device pixels, then that image is not scaled, since 100×2 = 200. However on a lower DPI display that might not have any zoom factor set, the 200×200 image would be properly downscaled to 100×100.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The basic strategy here is two-fold. First, we provide a graphic whose dimensions are &lt;em&gt;greater than the dimension we intend on displaying them at&lt;/em&gt;. This means if we want to display a 50x50 pixel image we use a 100x100 or 200x200 pixel image instead. Then, we resize our nice large image back down to 50x50 pixels (using either CSS or the width and height attributes). The net effect here is that when you zoom in on your image, the High DPI display will show all that extra pixel information, while normal displays will be none the wiser.&lt;/p&gt;

&lt;p&gt;What does this &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; magic have to do with our friendly &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element? As it so happens, we can apply this same exact strategy. If we draw out our &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; &lt;em&gt;larger&lt;/em&gt; than we need it to be, then resize it back down, we get nice, crisp artwork even when you right up in its grill. So instead of drawing your 50x50 pixel canvas artwork at 50x50 pixels, try drawing a 100x100 pixel (200x200, 800x800, whatever you please) &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element and then shrinking it back down to 50x50 pixels in CSS.&lt;/p&gt;

&lt;p&gt;You can actually see this at work in the Vimeo video player:&lt;/p&gt;

&lt;p&gt;&lt;br/&gt;&lt;strong&gt;Awesome&lt;/strong&gt;:
&lt;img src="http://f.cl.ly/items/373b3M0x331g0x1G2C3z/Image%202011.07.27%204:34:55%20PM.png" alt="Awesome"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;br/&gt;&lt;strong&gt;Not so Awesome&lt;/strong&gt;:
&lt;img src="http://f.cl.ly/items/3r1d1L3o3e2x3W0s0h14/Photo%20Jul%2027,%204%2028%2042%20PM.png" alt="Not so Awesome"/&gt;&lt;/p&gt;

&lt;p&gt;&lt;br/&gt;
What&amp;#8217;s really great about using this technique with the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element versus simply linking to a larger image within the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag is that since graphics are being drawn client-side you&amp;#8217;re not loading extra bytes over the network that are potentially 2-4 times larger than you really need&lt;sup id="fnref:p8141645542-2"&gt;&lt;a href="#fn:p8141645542-2" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Script on!&lt;/p&gt;

&lt;p&gt;Further reading:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;a href="http://menacingcloud.com/?c=highPixelDensityDisplays"&gt;Optimising for High Pixel Density Displays&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.sencha.com/blog/resolution-independent-mobile-ui"&gt;Resolution Independent Mobile UI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;div class="footnotes"&gt;
&lt;hr&gt;&lt;ol&gt;&lt;li id="fn:p8141645542-1"&gt;
&lt;p&gt;I think some of the confusion stems from how the word vector is used in relation to &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt;. The &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; API is “vector” in the mathematical/physical sense, meaning a line is drawn by defining a direction, and a magnitude. It is &lt;em&gt;not&lt;/em&gt; vector in the sense that the graphics are re-drawn each time the view updates (ie. when you zoom in). Once &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; graphics are drawn, they exists as rasterized pixels and cannot be manipulated as separate objects, unlike &lt;a href="https://developer.mozilla.org/en/SVG"&gt;SVG&lt;/a&gt;. &lt;a href="#fnref:p8141645542-1" rev="footnote"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn:p8141645542-2"&gt;
&lt;p&gt;Ah yes, there&amp;#8217;s always a footnote next to a sentence saying there&amp;#8217;s no downside. While it&amp;#8217;s true you&amp;#8217;re not loading in extra-large artwork, saving you the cost of transferring that over the network, you still are drawing 2-4 times as many pixels on the screen. This can potentially have an effect on drawing speed, memory usage, and animation performance. So just be aware of these caveats and test often. &lt;a href="#fnref:p8141645542-2" rev="footnote"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;&lt;/div&gt;</description><link>http://reusablebits.com/post/8141645542</link><guid>http://reusablebits.com/post/8141645542</guid><pubDate>Wed, 27 Jul 2011 16:56:00 -0400</pubDate><dc:creator>josephschmitt</dc:creator></item><item><title>Simple Class-based Function Pattern for JavaScript</title><description>&lt;a href="https://forrst.com/posts/Simple_Class_based_Function_Pattern_for_JavaScri-ISC"&gt;Simple Class-based Function Pattern for JavaScript&lt;/a&gt;: &lt;p&gt;Some sample code and an overview of a neat, simple pattern &lt;a href="http://bdougherty.tumblr.com"&gt;Brad&lt;/a&gt; and I used when we wrote the&lt;a href="http://vimeo.com/blog:391"&gt; HTML Player&lt;/a&gt; over at Vimeo:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When your JavaScript code gets loaded tens of thousands of times a minute, every little byte counts. Therefore, right at the outset we wanted to come up with a simple pattern around which we could structure our code that would allow us great flexibility (we’d be developing 3 players, afterall: Desktop, Mobile, and Touch) but would also lend itself to good compression before deployment (in our case via Google’s Closure Compiler).&lt;/p&gt;
  
  &lt;p&gt;Now, there are many, many, &lt;em&gt;many&lt;/em&gt; things that we did to bring our video player source code to its svelte ~25k, but one of the techniques was to be extremely precise in scope for our class methods. Above you can see some stubbed-out code that illustrates the three different types of class methods we used: Private, Privileged, and Public.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Click through to see the sample code as well as explanations for the three method types.&lt;/p&gt;</description><link>http://reusablebits.com/post/7778373200</link><guid>http://reusablebits.com/post/7778373200</guid><pubDate>Mon, 18 Jul 2011 18:56:00 -0400</pubDate><dc:creator>josephschmitt</dc:creator></item><item><title>Say Hello to Snipe</title><description>&lt;p&gt;Over the past few weeks I&amp;#8217;ve taken it upon myself to &lt;a href="http://docs.python.org/tutorial/index.html"&gt;learn Python&lt;/a&gt;. Learning a new programming language is fun and all, but it requires a ton of work and a ton of research. All of this research has left me with a lot of open tabs and windows that look a bit like this:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_lh37x3mjtI1qz6cob.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;Or if you&amp;#8217;re a &lt;a href="http://craigiam.tumblr.com/"&gt;crazy Chrome user&lt;/a&gt;, like this:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_lh398fXcrP1qz6cob.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;Finding a specific tab in that mess is no fun, especially when you have multiple tabs open from the same site, leaving all your tabs looking the exact same, starting with the same words. I thought there must be a better way to handle this when it occurred to me that the same problem exists on your operating system when looking for Apps, and OS makers have come up with &lt;a href="http://www.apple.com/macosx/what-is-macosx/spotlight.html"&gt;some&lt;/a&gt; &lt;a href="http://quicksilver.en.softonic.com/mac"&gt;great&lt;/a&gt; &lt;a href="http://windows.microsoft.com/en-US/windows7/Whats-new-with-the-Start-menu"&gt;solutions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Since this solution is so natural and intuitive, I thought it would be a perfect fit to apply the same idea to searching your browser tabs and windows, and Snipe is the product of that:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_lh37wioTLf1qz6cob.jpg" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;To bring up Snipe, you simply press Ctrl + Alt + Space &lt;sup id="fnref:p3468613560-1"&gt;&lt;a href="#fn:p3468613560-1" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt; on any open tab&lt;sup id="fnref:p3468613560-2"&gt;&lt;a href="#fn:p3468613560-2" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt;, and up pops the input field. Begin typing and, automagically, results from your open tabs (in any window!) start appearing. Use your keyboard to select which tab you&amp;#8217;d like, and Snipe will switch you to that tab and get out of your way. Snipe searches both the title and the url of your tabs, so fear not if you&amp;#8217;re looking for your Facebook tab but don&amp;#8217;t remember what page it&amp;#8217;s on. Also, searching is &amp;#8220;fuzzy&amp;#8221;, meaning you don&amp;#8217;t have to get the content exactly right to get a result, and the results are smartly sorted by which one Snipe thinks is the most relevant based on your key words.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve shared this extension with some people around the office and they really seem to like it. I know I&amp;#8217;ve found myself using it constantly throughout the day, so I&amp;#8217;m excited to see if other people find Snipe as useful as I do. Check out the download links below to install the extension (Chrome and Safari only) and, like all the projects I post on Reusable Bits, Snipe is also available for you to &lt;a href="https://github.com/josephschmitt/Snipe"&gt;fork on Github&lt;/a&gt; to make your own additions and contributions. I&amp;#8217;d love to hear about any feature ideas you have on the extension (there&amp;#8217;s already a couple ideas I have in a todo on the Github page) so feel free to leave any brainstorms in the comments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://s3.amazonaws.com/gosnipe.in/Snipe.safariextz"&gt;Snipe for Safari&lt;/a&gt; | Snipe for Chrome (&lt;a href="https://chrome.google.com/webstore/detail/glmjakogmemenallddiiajdgjfoogegl"&gt;Web Store&lt;/a&gt;) (&lt;a href="https://s3.amazonaws.com/gosnipe.in/Snipe.crx"&gt;Direct Download&lt;/a&gt;) | &lt;a href="https://github.com/josephschmitt/Snipe"&gt;Source on Github&lt;/a&gt;&lt;/p&gt;

&lt;div class="footnotes"&gt;
&lt;hr&gt;&lt;ol&gt;&lt;li id="fn:p3468613560-1"&gt;
&lt;p&gt;For Chrome users of Snipe, you have a couple other options as well. Snipe will work as a popup window with the regular Ctrl + Alt + Space shortcut, but it also shows up as a button in your toolbar and clicking that button will invoke the Snipe UI. Also, for the super-savy Chrome users, you can take advantage of Chrome&amp;#8217;s &lt;a href="http://blog.chromium.org/2011/02/extending-omnibox.html"&gt;Omnibox&lt;/a&gt;. Simple type &amp;#8220;tabs&amp;#8221; into the Omnibox and then hit the TAB key, and begin searching for your tabs as normal. You&amp;#8217;ll see your Snipe results show up built right in to Chrome. &lt;a href="#fnref:p3468613560-1" rev="footnote"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn:p3468613560-2"&gt;
&lt;p&gt;After you first install the extension you&amp;#8217;ll have to either refresh all of your open tabs or restart your browser to get the keyboard shortcut to work. Sorry, but I don&amp;#8217;t think there&amp;#8217;s a way around this! &lt;a href="#fnref:p3468613560-2" rev="footnote"&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;&lt;/div&gt;</description><link>http://reusablebits.com/post/3468613560</link><guid>http://reusablebits.com/post/3468613560</guid><pubDate>Wed, 23 Feb 2011 15:31:00 -0500</pubDate><dc:creator>josephschmitt</dc:creator></item><item><title>Clamp.js v0.2: Explanations and Performance Updates</title><description>&lt;p&gt;A couple of weeks ago I &lt;a href="http://reusablebits.tumblr.com/post/2642059628/introducing-clamp-js"&gt;released&lt;/a&gt; a cool little utility called &lt;a href="https://github.com/josephschmitt/Clamp.js"&gt;Clamp.js&lt;/a&gt; that helps with clamping (ie. adding ellipsis to) long pieces of html text. I was pretty excited about its release, though I stated that one downside was that performance improvements could be made on it since it loops character-by-character through a piece of text, checking to see if it fits each time.&lt;/p&gt;

&lt;p&gt;After some really constructive conversations with people on twitter and on this blog, I made some updates to how Clamp.js loops through text looking for a good fit. However, before I go into that, it&amp;#8217;s probably constructive to visualize how Clamp.js used to work.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;&lt;strong&gt;Clamp.js v0.1&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;object width="613" height="344"&gt; &lt;param name="flashvars" value="offsite=true&amp;amp;lang=en-us&amp;amp;page_show_url=%2Fphotos%2Fjayjo221%2Fsets%2F72157625801092311%2Fshow%2F&amp;amp;page_show_back_url=%2Fphotos%2Fjayjo221%2Fsets%2F72157625801092311%2F&amp;amp;set_id=72157625801092311&amp;amp;jump_to="&gt;&lt;param name="movie" value="http://www.flickr.com/apps/slideshow/show.swf?v=71649"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/slideshow/show.swf?v=71649" allowfullscreen="true" flashvars="offsite=true&amp;amp;lang=en-us&amp;amp;page_show_url=%2Fphotos%2Fjayjo221%2Fsets%2F72157625801092311%2Fshow%2F&amp;amp;page_show_back_url=%2Fphotos%2Fjayjo221%2Fsets%2F72157625801092311%2F&amp;amp;set_id=72157625801092311&amp;amp;jump_to=" width="613" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;&lt;p&gt;Step one is figuring out how much we want to clamp. In this example, we want to clamp this 9 line piece of content down to 7 lines, visualized by the red line.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, Clamp.js selects the last character.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then it adds ellipsis and checks to see if the condition has been satisfied (the condition being 7 lines of text). The condition hasn&amp;#8217;t been met, so it removes the currently selected letter and tries again with the next.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is repeated until it finally does meet the condition and the component is finished.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;As you can see, this method certainly &lt;em&gt;works&lt;/em&gt;, but it&amp;#8217;s a bit of a brute force method of doing things. It works particularly well when clamping short sentences or phrases like headings (which is what I originally wrote this plugin for), but is less than optimal when clamping long pieces of text line blog entries where you only need to display a few lines.&lt;/p&gt;

&lt;p&gt;One popular suggestion was to be able to declare which direction to clamp from, either from the back to the front or from the front to the back. This would allow you to use back-to-front clamping for headings and front-to-back clamping for paragraphs. This is a good suggestion and one that I will most likely implement in the future, but I also wanted to address the performance of the clamping engine itself.&lt;/p&gt;

&lt;p&gt;After a few back-and-forths with &lt;a href="http://dropshado.ws/"&gt;Dave DeSando&lt;/a&gt; on Twitter, I came up with the following (quite clever, I feel) solution for speeding up clamping:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clamp.js v0.2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;object width="613" height="344"&gt; &lt;param name="flashvars" value="offsite=true&amp;amp;lang=en-us&amp;amp;page_show_url=%2Fphotos%2Fjayjo221%2Fsets%2F72157625926454240%2Fshow%2F&amp;amp;page_show_back_url=%2Fphotos%2Fjayjo221%2Fsets%2F72157625926454240%2F&amp;amp;set_id=72157625926454240&amp;amp;jump_to="&gt;&lt;param name="movie" value="http://www.flickr.com/apps/slideshow/show.swf?v=71649"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;embed type="application/x-shockwave-flash" src="http://www.flickr.com/apps/slideshow/show.swf?v=71649" allowfullscreen="true" flashvars="offsite=true&amp;amp;lang=en-us&amp;amp;page_show_url=%2Fphotos%2Fjayjo221%2Fsets%2F72157625926454240%2Fshow%2F&amp;amp;page_show_back_url=%2Fphotos%2Fjayjo221%2Fsets%2F72157625926454240%2F&amp;amp;set_id=72157625926454240&amp;amp;jump_to=" width="613" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;

&lt;p&gt;Before we even start, there&amp;#8217;s a new option in Clamp.js called splitOnChars which is an array of string characters. What this array does is tell the component how it should try and grab large chunks to try and remove before it resorts to going character-by-character. For example, the default array might look like this: [&amp;#8216;.&amp;#8217;, &amp;#8216;,&amp;#8217;, &amp;#8217; &amp;#8216;]. What that&amp;#8217;s telling Clamp.js is to try removing chunks based on periods (ie. sentences), then try chunks based on commas (sentence fragments), and finally spaces (words). This allows us to remove larger pieces of text at a time before falling back on character-by-character removals. Using the above array, here&amp;#8217;s what the new Clamp.js does:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;&lt;p&gt;Our first character to split on is a period, so Clamp.js finds the last period in our text.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It then selects everything after the character, giving us our first large chunk. Notice how much larger this chunk is than just a single character.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clamp.js next tries removing this entire chunk to see what happens. If removing it still leaves us with a phrase that&amp;#8217;s too long, it&amp;#8217;ll try removing the next chunk/sentence. In this case however, it seems we&amp;#8217;ve removed too much.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since we&amp;#8217;ve removed too much, we&amp;#8217;ll go to the next split-character on the list, which is a comma. Clamp.js finds the last comma.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It selects the fragment after the comma.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The fragment is removed. You&amp;#8217;ll notice that this time the text is still too long, so it&amp;#8217;ll select the next comma and try again. However, that &lt;em&gt;is&lt;/em&gt; too much. So we&amp;#8217;ll have to move on to the last split-character: the space.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It finds the last space in the text.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Selects everything after that space.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;That last fragment is removed. It&amp;#8217;s still too long, so it&amp;#8217;ll try doing so again, but doing so again makes it too short. So we move on to the last and final split-character which is splitting on each individual character. This last one doesn&amp;#8217;t have to be in the array because the last step will &lt;em&gt;always&lt;/em&gt; be splitting on single characters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The last character is selected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The character is removed and it adds ellipses to see if it fits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This step is repeated until there is an exact fit.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Using this technique, we can remove really large chunks really quickly, and gradually narrow down our search until we go character-by-character on the final word. How much more efficient is this? Well, just in this example, with v0.1 Clamp.js would have looped around 29 times. With v0.2, it only has to loop 7! If that&amp;#8217;s not an improvement, I don&amp;#8217;t know what is!&lt;/p&gt;

&lt;p&gt;The real neat thing about this is you can submit your own array of characters that you want Clamp.js to split on. Suppose your text has a lot of exclamation points. Then you can submit an array that includes those to try to speed up the process. I&amp;#8217;m pretty excited about these improvements and can&amp;#8217;t wait to hear what you think of them. Drop me a line via email or let me know how you feel publicly in the comments below.&lt;/p&gt;</description><link>http://reusablebits.com/post/2980974411</link><guid>http://reusablebits.com/post/2980974411</guid><pubDate>Fri, 28 Jan 2011 16:34:00 -0500</pubDate><dc:creator>josephschmitt</dc:creator></item><item><title>Introducing Clamp.js</title><description>&lt;a href="https://github.com/josephschmitt/Clamp.js"&gt;Introducing Clamp.js&lt;/a&gt;: &lt;p&gt;Recently, while working on some last-minute fixes for the Vimeo HTML player, I ran into a limitation of current-gen browsers that really frustrated me. It seems that there is no standardized, supported way to clamp an HTML element. What do I mean by clamp? If you have a design which limits your text to be only 2 or 3 lines long, but the text is dynamic and so can be any length it damn well pleases, clamping will ensure the text gets chopped off at the appropriate height and will add ellipsis at the end to denote that the content has been interrupted.&lt;/p&gt;

&lt;p&gt;I did some research and found &lt;a href="http://dropshado.ws/post/1015351370/webkit-line-clamp"&gt;Dave DeSandro’s entry&lt;/a&gt; about -webkit-line-clamp which, through applying some seemingly unrelated and random CSS styles, does achieve this effect… sort of… most of the time. Here’s an example of some properly clamped text in our wonderful video player:&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img src="http://media.tumblr.com/tumblr_leoc939Ngn1qz6cob.jpg" style="float: none; display: inline;"/&gt;&lt;/p&gt;

&lt;p&gt;Great! That works! Well… sort of. Here’s what happens if your HTML element just happens to have a link as the last node of the element:&lt;/p&gt;

&lt;p style="text-align: center;"&gt;&lt;img src="http://media.tumblr.com/tumblr_leoc9dbUf91qz6cob.jpg" style="float: none; display: inline;"/&gt;&lt;/p&gt;

&lt;p&gt;Whoops. It’s actually inserting the link from the very end of the paragraph even though it should be getting cut off. As &lt;a href="http://twitter.com/#!/desandro/status/23381458039078912"&gt;Dave explained&lt;/a&gt; to me, -webkit-line-clamp is not only vendor-specific, it’s completely undocumented and experimental, so it can’t really be used reliably.&lt;/p&gt;

&lt;p&gt;Instead of admitting defeat I decided to write my own solution (I mean how hard can it be, right?). Well, it turns out it wasn’t that difficult at all, and the results are &lt;a href="https://github.com/josephschmitt/Clamp.js"&gt;hosted over on Github&lt;/a&gt;. You can give it how many number of lines you want your content to be, how many pixels high you want it to be, or a setting of “auto” where it’ll fit as much as it can in a given area and then automatically clamp itself. If you’re using a browser that supports the wonderful -webkit-line-clamp it’ll attempt to use it (though you can force to turn it off as well), otherwise it’ll fall back to a JavaScript-based solution.&lt;/p&gt;

&lt;p&gt;There are, of course, some caveats with using it. First, it can be a little expensive performance-wise if used incorrectly. Clamp.js works by removing one character at a time from the end of the content until it fits inside a designated area. That means that if your content is 30 lines long and it needs to get down to 2 lines, it’s going to loop hundreds and hundres of times until it gets from 30 to 2 lines. This is something I want to improve on at some point, but for now just be aware of this. Second, I haven’t done too much extensive testing (that’s what you guys are for!) so there are bound to be bugs. Don’t use this in mission critical projects just yet.&lt;/p&gt;

&lt;p&gt;Other than that feel free to use the heck out of it and give me some feedback. I would love to know what you think!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href="http://reusablebits.tumblr.com/post/2980974411/clamp-js-v0-2-explanations-and-performance-updates"&gt;Performance updates&lt;/a&gt; released with v0.2.&lt;/p&gt;</description><link>http://reusablebits.com/post/2642059628</link><guid>http://reusablebits.com/post/2642059628</guid><pubDate>Fri, 07 Jan 2011 17:43:00 -0500</pubDate><dc:creator>josephschmitt</dc:creator></item></channel></rss>
