Saturday, September 13, 2014

Unresponsive Scripts and Javascript's Lack of Sleep



Working on a single-page app using a MV* library? You've probably had this wonderful dialog popup at some point. If your Javascript is running without taking a breadth, the browser will get chippy and start alerting the user that something has gone awry. While its most likely true, popping up messages the user doesn't understand really doesn't help. Even worse are the solutions to turn off Javascript because many sites still function even if scripting is disabled. Unfortunate advice in today's Internet.

In many cases, its a loop with a significant number of iterations that is probably triggering any number of more complex operations. Without yielding to the browser from time-to-time, it will create an unresponsive experience for your user (dialog or not). If you've programmed in other languages, you're immediate go to solution might be to sprinkle in time kind of sleep calls in those process intensive loops. Unfortunately, there is no sleep function in Javascript. The only mechanism to break out of a call stack is the setTimeout function. However, it does not work like sleep in other languages where the current execution point blocks while something else runs and then returns back to the next line after the sleep timeout. Instead, it just keeps on running:

Monday, September 8, 2014

Multi-Option Picker using Bootstrap Dropdowns with Checkboxes

I wanted check boxes in my Bootstrap dropdown menu so the user could pick from several different options and see which options were already selected. The menu's default behavior is to hide once the user clicks on it. This meant I needed to cancel the click event to prevent that behavior. Unfortunately, if the user clicked a checkbox, it wouldn't show as checked since the click was being canceled (try clicking the checkbox versus the anchor and notice how it doesn't toggle):

See the Pen Bootstrap Dropdown with Checkboxes: Can't Check by bseth99 (@bseth99) on CodePen.



For reference, this is the markup for the dropdown with the checkboxes:


<ul class="dropdown-menu">
<li>
<a href="#" class="small" data-value="option1" tabIndex="-1">
<input type="checkbox"/>&nbsp;Option 1
</a>
</li>
<li>
<a href="#" class="small" data-value="option2" tabIndex="-1">
<input type="checkbox"/>&nbsp;Option 2
</a>
</li>
<li>
<a href="#" class="small" data-value="option3" tabIndex="-1">
<input type="checkbox"/>&nbsp;Option 3
</a>
</li>
<li>
<a href="#" class="small" data-value="option4" tabIndex="-1">
<input type="checkbox"/>&nbsp;Option 4
</a>
</li>
<li>
<a href="#" class="small" data-value="option5" tabIndex="-1">
<input type="checkbox"/>&nbsp;Option 5
</a>
</li>
<li>
<a href="#" class="small" data-value="option6" tabIndex="-1">
<input type="checkbox"/>&nbsp;Option 6
</a>
</li>
</ul>


My goal is to use one event handler for both the anchor and the check box. On each click, toggle the option, and ensure the check box reflects this choice. When you click the anchor, the check box needs to be set. However, if you click the check box, it wouldn't need to be set, but to be consistent and use one handler, I just set it anyways (I saw no reason to add any more sophisticated element detection to the code):

var options = [];

$( '.dropdown-menu a' ).on( 'click', function( event ) {

   var $target = $( event.currentTarget ),
       val = $target.attr( 'data-value' ),
       $inp = $target.find( 'input' ),
       idx;

   if ( ( idx = options.indexOf( val ) ) > -1 ) {
      options.splice( idx, 1 );
      $inp.prop( 'checked', false );
   } else {
      options.push( val );
      $inp.prop( 'checked', true );
   }

   $target.blur();

   return false;
});
I want the return false in there to prevent the dropdown from closing and, secondarily, to ensure the href="#" doesn't affect my router. I could remove the href from the anchor, but then I'd lose the hand cursor on hover. I could style it have the cursor, but I'd still be left with the auto-closing menu which I don't want since the user may want to pick other options. That leaves me with the conundrum of dealing with a direct click on the box which also is a click on the anchor which needs to be canceled but canceling it also doesn't check the box properly. I can think of several ways around it - all adding way more code than makes sense for such a seemingly simple problem. After some toiling, I finally found a very easy work-around. It occurred to me that I just needed to check the box after all the events finished running. That means I needed to be outside the current call stack to check the box. Using setTimeout with a zero delay does just that so I wrapped that bit of code in a setTimeout and - viola - working checkboxes:


   setTimeout( function() { $inp.prop( 'checked', true ) }, 0);



And here's the whole working example:

See the Pen Bootstrap Dropdown with Checkboxes: Working by bseth99 (@bseth99) on CodePen.



And with that, the Bootstrap drop down become just that much more useful.

Tuesday, September 2, 2014

Triggering CSS-Only :hover and :focus Transitions

I've been making an attempt to use CSS-only for transitions including actually triggering them. The best mechanism to trigger a transition is using the :hover pseudo-select on an anchor tag. Other than :focus, its really the only one which will reset its state. I've seen hacks using :active and :target but it seem those are really stretching what makes sense based on the capabilities of CSS. To really eliminate JS, more state selectors are needed that enable attaching transitions and animations. For now, I'm exploring using :hover to create a simple carousel-like widget.

Before jumping into the final project, I quickly tested the idea:

See the Pen Simple No-JS Hover Animation by bseth99 (@bseth99) on CodePen.



This is a very simple case to play with the idea. With some actual styling, it would work really well as tooltip. You can see the .pop class defines the transition and the initial state of the element. The :hover selector is used to change the value which causes it to animate into view.

Moving on to the carousel idea, I setup three anchors which serve as hot spots to quickly transition to that slide in the widget. I also setup the carousel to continuously animate through each slide until the user hovers over the anchor which interrupts the normal animation and immediately transitions to the slide represented by the link:

See the Pen Hnoxg by bseth99 (@bseth99) on CodePen.



The difference in this setup compared to the simple case above, is instead of embedding the transitioning content into the anchor tag, the whole carousel is a sibling of each of the anchors. This relationship makes it possible to add other anchors tags to the slides as needed and makes the whole setup easier. Selecting those elements uses a selector I've rarely used (if ever). The "~" will select a sibling inside the same parent even if its not adjacent to another element. This is important since I have more than one anchor and clearly the first one is not immediately next to the main carousel element.

The next step is to define the transition and animation on the carousel. They are attached to the .slider element which is a child of the main carousel element. Its setup to scroll inside this container which hides the overflow to create the illusion of only one slide showing at a time. Each slide then becomes a child of slider with unique class names so they can be targeted as the mouse hovers over each anchor:

.scroller {
  transition: left 400ms ease-in-out;
  animation: autorun 5s;
  animation-delay: 500ms;
  animation-iteration-count: infinite;
}


Before forcing the transition, the animation needs to be turned off, otherwise, it will get jumpy:

.trigger:hover ~ .container > .scroller {
   animation: none;
}


Then, each position can be defined for the slides:

.trigger:hover.r ~ .container > .scroller {
  left: 0;
}

.trigger:hover.g ~ .container > .scroller {
  left: -100px;
}

.trigger:hover.b ~ .container > .scroller {
  left: -200px;
}


One additional improvement is to allow the user to click which will hold the current slide in place. Right now, as soon as you hover off the anchor, the carousel rewinds to the beginning and starts the animation over again. We can take advantage of the fact that when you click on an anchor it receives focus and remains there until clicking off the element. Only a few minor changes are required to add this feature. First, the above .trigger:hover styles need to include an additional .trigger:focus selector:

.trigger:hover.r ~ .container > .scroller,
.trigger:focus.r ~ .container > .scroller {
  left: 0;
}

...



And to enable the anchor to be focusable, the tabindex needs to be set:

<a href="#" class="trigger r" tabindex="0">
</a>



Here is the revised version using both :hover and :focus to create the interaction with the widget:

See the Pen iobaE by bseth99 (@bseth99) on CodePen.



Its fairly simple but if you don't need anything exotic you can get by quite well with some carefully laid out HTML which takes advantage of the abilities of CSS. While I called this a carousel, it certainly is not limited to that design. Any situation that calls for links that transition through some set of content can take advantage of this approach without any need to write a line of Javascript.

Monday, August 25, 2014

Caching Ruby Sequel Models to Reduce Object Allocations and Database Load

Caching seems to be an inevitable part of most applications. The strategies you employ application-to-application will differ depending on use. Write intensive areas will receive little benefit while read intensive areas can see significant performance boosts. As you design and build your application, you should be able to name off data stores that remain fairly static and can readily be held in memory with little risk of becoming stale. I've been using the Sequel ORM to build my models on PostgreSQL and my number one candidate for caching are contact details. Just about everything output from the application include at least one, if not 20 or more references to the contact model. Further research found that within one request, many contact lookups were actually the same contact record which made it a perfect candidate for caching at least within the request.

Since most of these references are done through a primary key lookup on the table:

   ...
   contact = Contact[other_object.contact_id]
   ...


I figured I could proxy the [] method on the class and add my caching logic there.

I found a gem called lru_redux which, if using Ruby 1.9+, takes advantage of the fact that a Hash is ordered. This makes a very efficient and easy to use LRU cache to keep a finite set of very active models:

class Contact < Sequel::Model
   attr_accessor :last_reload_time

   class << self
      
      @@cache = LruRedux::Cache.new(100)
     
      # Override [] to add in caching logic
      def []( rid )
         if ( rec = @@cache[rid] )
            # Model is found in cache, no need to load it from the DB
            if rec.last_reload_time < 5.minutes.ago
               # Cached model instance is stale, reload it
               rec.reload
               rec.last_reload_time = Time.now.utc
            end
         else
            rec = super(rid)
            if rec
               # Don't cache nil models (id not found in DB)
               rec.last_reload_time = Time.now.utc
               @@cache[rid] = rec
            end

         end
         rec
      end
   end

end


Since I'm going to leave the models in memory between requests, I still need to ensure a model doesn't get stuck there indefinitely without reloading on a periodic basis. Maintaining the last_reload_time instance variable ensures data stay fairly up-to-date. Since I know these don't change too often, five minutes is probably conservatively low. You might also ask why not just reload the model when it changes? That reload would only be local to the current process and not across the multiple processes spread over several servers I have running. Those other processes have no knowledge of the change and, in an effort to not make this more complicated, I settled on a simple timeout and fairly short LRU list.

With the above caching strategy, I chopped a few hundred milliseconds off my most used end point. The savings really were two-fold. First, the caching removes the round trip to the database and the processing time required to parse the data and build the model. Secondly, because these objects are more persistent, there is less object allocations on each request and thus, less garbage collection. Since GC gets expensive, reducing that alone made a significant improvement.

The above example may not solve every problem. There's no replacement for studying your application's specific request patterns, execution paths, and data structures. Performance tuning is not a simple task but having as many tools at your disposal to solve various bottlenecks can make the process a whole lot smoother.

Saturday, June 28, 2014

Learning to Graph with D3

I've been meaning to play with D3 for quite some time. Maybe the only thing stopping me was the seemingly overwhelming amount of features available in the library. There's a definite learning curve involved to get in the right mindset required to use D3. However, once you get there, its actually really easy to use and, surprisingly, does a lot of the heavy lifting for you. As you navigate through the documentation, you need to separate the basics from the advanced features. If you need a static graph, you only need to learn a subset of the library to be successful. Once you get that foundation in place, you can build into transitions, interactivity, and layouts.

For my first foray into the world of D3, I chose to keep things as simple as possible and focus on deconstructing the multivariate example graph to attempt to isolate the basic components of a graph. I was really interested in what was actually happening at each step and how the pieces fit together. Below, I'll attempt to iteratively build the example one feature at a time to get to the final product. I consider each step, a basic component of any graph so you should be able to take the pieces and assemble them together to rapidly start your own "first" graph.

Sunday, June 8, 2014

Searching for Patterns when Developing Browser Extensions

Browser plugin development has become as easy as writing a plain vanilla web application. The only difference is it's installed on the user's computer and has a lot more access to local resources. As such, many libraries and design patterns utilized in browser-based web applications can be reused within extension development. There are some quirks here and there to learn related to scope and security. However, most importantly, you'll have to rewrite portions of your extension to deploy it in different browsers (if they even support a HTML/JS based plugin). Both Chrome and Firefox offer APIs supporting a HTML/JS based plugins which is a good enough reason for me to explore the possibilities of what use cases I can find for them. I started with Chrome because Firefox has more installation requirements and, in my opinion, more development hurdles when you wanted to test your creation. Chrome simply requires you to make a directory and tell it to load the extension (and reload it after every change). That's the kind of simplicity I expect in my development environment.

Maybe the biggest learning curve when trying to build an extension for the first time is deciphering the terminology for the different execution contexts available in the application. Additionally, identifying what functionality exists in each execution scope that affects how to organize the extension's logic and any limitations that limit adopting techniques from traditional web application development. Using the diagram on the left as a guide, you can see there's really only two scopes to manage in an extension. One is the extension context and the other is the page context. Each browser platform names these differently, but the purpose of each is essentially the same. The challenge is decomposing several key components and identifying their role within each context. I've named a few pieces that I think make sense and, personally, would find useful when building an extension.

As I worked on my extension, it became apparent that a small layer of abstraction to facilitate the interaction of the different contexts and normalize the creation of UI components to create a consistent mechanism for managing communication between scopes would be useful. Since I was starting in Chrome with aspirations of also deploying it in Firefox, I'd like to make as much of my extension reusable across different browser extension platforms. Chrome and Firefox have many similarities related to how to structure an extension, context isolation, security, and API capability. However, there are nuances and, the more those can be abstracted, the easier it will be to port between browsers.

The goal in this discussion is to investigate how to break up the extension into logical chunks and stub out a few key code blocks to help create some concrete examples of what parts of a final solution might look like. In subsequent posts, I'll build off of those pieces to create a simple library to encapsulate these core pieces and demonstrate how to use these components to build a simple extension.

Extension Context

Code that runs in the extension context has access to the full browser API, however, has no access to the page DOM. In Chrome, they use the terminology background pages, which have been confusingly split into "persistent" background pages and event pages. The responsibilities placed on this area of the program include providing access to the browser API, activating the extension, managing extension level UI pages, and storing/retrieving global settings/data. Visually, you can add an icon to the toolbar which enables user interaction from the browser level regardless of the site or content displayed in the browser.

Extension Controller

Early on, it was apparent that the primary role of the "background page" was to act as a main messaging hub and maintain application state. As such, all the other components will ask for services or information through the browser's messaging services (in Chrome its part of the runtime API) using a request/response pattern:

chrome.runtime.onMessage.addListener(

   function( request, sender, sendResponse ) {
      // request has two keys - topic and data
      // topic is a string, data is a hash relevant to the topic
      // which the handler will understand
      switch ( request.topic ) {

         case 'subject.scope':

            sendResponse({ foo: bar });
            break;

         ...
      }
   }

);


This chunk of code implements the line labeled "A" in the above diagram. The important thing to note in the code is the structure of the message. The request is an object containing a "topic" and related "data" keys. The topic is a string structured with both a subject and a scope to help avoid collisions. You might use topics like "user.data" to fetch data about the current user, "user.login" to start the authentication process, or "site.monitor" to register a callback when certain conditions are met using the Chrome events API. In any case, its an opinionated structure to the messaging that is not inherently enforced in the browser API so we want something that can help ensure that there is consistency to the requests.

Popup

A popup in the extension context is a UI component that can run any web page content inside a browser provided window outside the context of the page. These pages are useful for collecting settings or information required by the extension to customize the user experience. Technically, a popup is not even required. You can load these pages into a new tab and offer a complete web application inside the browser without connecting to a server to download the content. You're extension could run as a locally installed web application activated by clicking a button on the browser tool bar. Granted, distributing updates to your application requires more effort but its an interesting concept for building client-side web apps.

Activating your popup or page can happen in one of two ways. Either it can be automatically triggered based on the manifest.json configuration:

  "browser_action": {
      "default_title": "My Bookmarks",
      "default_icon": "icon.png",
      "default_popup": "popup.html"
  },


Or, you can manually open a page in a tab or popup from the background page:

chrome.browserAction.onClicked.addListener(function(tab) {
  var manager_url = chrome.extension.getURL("manager.html");
  focusOrCreateTab(manager_url);
});


The former is obviously easier and works well if you only have one page that needs to be displayed. The latter example offers significantly more control and comes in handy if different pages should be displayed under different conditions. I'd guess that most extensions can implement one popup page to enable extension level user interaction and that's why there is a section to configure it in the manifest. In the extension I'll be building, there is only one popup page to collect some user specific data. Everything else operates inside the page context.

Page Context

Code running inside the page scope can access the DOM of the currently loaded page. Anything you would do in a normal web page to query and manipulate the DOM, you can do in this scope. The biggest difference is that all the code loaded in this context is isolated from any code running on the page. If jQuery is loaded on the current site, you're extension code can't use it. You must load your own copy of jQuery. The only thing shared between the page loaded in the browser window and the extension is the DOM.

Since you can manipulate the DOM, you can inject content into the current site. While this may seem great, in practice it may not be the best approach. Injecting anything into the DOM is subject to the current styling of the page which may cause undesirable results on the injected markup. Visa versa, any style sheets injected into the page may adversely affect the page and disrupt the functionality of the current site. As such, only minor changes should be made and maybe only when you know exactly how the site reacts to those changes. More elaborate UI elements need to be isolated from the current page.

Based on these considerations, I've broken the page context into three pieces. First, a controller manages all the components in the page context and any communication with the extension context. Second, a monitoring agent helps identify interesting events to the current site which the extension may want to use to trigger an action. Finally, an iframe container builds the foundation for UI components that will be instantiated to allow user interaction within the page.

Page Controller

This part of the extension is used to manage any logic required at the page context. Its primary purpose is to monitor events from page content detectors, manage the UI frames life-cycle, and bridge requests to the extension context. From a framework perspective, the UI frame component is broken into two pieces. On the controller side, there is a portion to send and receive messages from the iframe window and handle life-cycle events. These parts will be reflected on the iframe side of the library to handle the same activities but from the frame's perspective. Using messages, we can communicate between windows:

   
   // Receive messages from parent controller
   window.addEventListener( 'message', ... )

   // Send messages to parent controller
   // This is inside an abstraction layer to normalize
   // identifying each iframe to ensure proper message
   // routing
   function notify( topic, data ) {
      var win = this.$iframe[0].contentWindow,
          message = JSON.stringify({ target: this.cid, topic: topic, data: data });

      win.postMessage( message, this.$iframe[0].src );
   };

   // Send message to extension context for processing
   function request( topic, data ){
      chrome.runtime.sendMessage( { topic: topic, data: data }, function( response ) {
         ...
      });
   };


This API can only pass strings between the windows so all the data needs to be serialized and deserialized when working with the method and events. I chose a similar strategy to structuring the message that I used in the extension context to keep things consistent. The library can wrap this logic in a way to allow passing basic Javascript object hashes between the main window and its iframe children. The messaging will broadcast to all the children frames so its necessary to identify which one should respond to the event. Since the main window side of the iframe view will be an object instance representing the iframe, it can identify itself and creatively set the URL on the iframe so it can know its identity and respond accordingly. The cid above accomplishes this along with the src in the postMessage call. Between the two mechanisms, you can ensure secure communication is maintained between the two windows.

UI Frame

The iframe component enables isolating styling from the site's content. Since its own window as well, you can run anything inside it to create the view displayed to the user. If you want to build something fancy, you can use Backbone, Angular, or any other framework you'd like. Minimally, you will want to add a little logic to help wrap the messaging between the main window and the iframe window to ensure consistent communication:

   
   // Receive messages from parent controller
   window.addEventListener( 'message', ... )

   // Send messages to parent controller
   function notify( topic, data ) {
      window.parent.postMessage( JSON.stringify({ source: window.location.href, topic: topic, data: data }), '*' );
   }


The only other issue to be aware of when running code in the iframe is working around cross-domain security policies. When I tried to render a Backbone view in an iframe I created, I had issues since the Underscore micro-template uses eval to inject data into the compiled template and render the view. To enable this feature, you have to add this line to your manifest file:

   "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"


Monitor/Detect

The final piece of the puzzle that may not always be important to every plugin is watching the target page for interesting changes. Since most sites dynamically load and generate content, its not good enough to wait for the page to load and check it for certain content. For instance, if you're creating an extension to perform actions with images found on a page, those images may only load as the user scrolls the page. If its a single page app, the page loads once and everything else renders inside that page dynamically. Instead of binding to the loaded event, you have to bind to a mutation event. However, these events fire often and are prone to crash if not used wisely. It was fortuitous that Addy Osmani wrote an article about DOM mutation observers because before I considered that approach, I was manually binding/unbinding and throttling the event:

function monitorChange() {
   $( document.body ).bind( 'DOMSubtreeModified', detectContent);
}

function unmonitorChange() {
   $( document.body ).unbind( 'DOMSubtreeModified', detectContent);
}

var detectContent= _.throttle(
      function() {

          var realChanges = 0;

          unmonitorChange();

          console.log( 'tree changed' );
          ...
          /* Find changes and do something, which may modify the DOM */
          ...

          monitorChange();
      },
      500,
      { trailing: false }
   );

detectContent();



Using the observer avoids both those solutions and even provides detail about the changes made. I'd still like to abstract this part slightly to provide selectors that should trigger different actions if that content is among the changes:
Detect.monitor({
   'insert img': function() {
      ...
   },

   'remove img': function() {
      ...
   }
});
Integrating that back into the page context's controller enables it to act on changes of interest and perform an appropriate action. Since the mutation observer API doesn't provide a robust query selector on exactly what to observe, this layer can provide that capability and dispatch an appropraite subset of targeted events.

Next Steps

So far I've only made a broad outline of the types of components I'd like to have when building a browser extension. Now its time to flush those pieces out so something useful can be built with them. I'm still a little early in my research and will definitely refine these concepts a bit. But after cobbling together a simple plugin, these were the main themes I saw emerging in my work.

Monday, May 12, 2014

State of the Stack: What Javascript Libraries Do You Use?

Every now and then I take a moment to reflect on the state-of-the-art and make sure I'm not heading the way of the dinosaurs. Every five years or so, the Internet seems to head in another direction (or at least starts to shift). Technologies and techniques get old fast and staying on top of the latest trends is important to remain relevant. Building your client stack probably starts with the selection of a MV* like library. What you choose will impact all aspects of your project. InfoQ has built a survey of adoption of various MVC libraries. You have to vote to see the results but it probably should not come as too big a surprise that Angular, Backbone, and Knockout are at the top of the list.

Interested in how that compares to another source, I turned to GitHub to look at popularity. The number of watches, stars, and forks is a pretty good indicator of relative adoption:



The "related" graph depicts how many results you get on GitHub when you search for one of these libraries. Its a reasonable indicator of the supporting ecosystem that has evolved around the library. Why is this important? By themselves, these libraries are not complete frameworks that allow you to build web apps. They do help solve the problem of separating data and logic from the DOM and establishing good design patterns. However, depending on your application, you'll need a lot more than these solutions to create the desired user experience. I've attempted to generalize the basic components you'll probably consider when building your application:



Each of the top three MVC libraries address parts of these areas and provide meaningful support to extend or integrate other solutions as necessary. The supporting community around these tools becomes important as you try to find existing solutions to meet your needs. The less you have to write and test the better. If it already exists and, is in reasonably high use, then you can feel comfortable that it will work and you can focus on solving problems unique to your application.

Today, I primarily use Backbone as my MVC. Its strength lies on the data side with a focus on abstracting the acquisition and persistence of data to the server. I typically swap out Underscore in favor of Lodash and drop in MomentJS to make date manipulation a breeze. On the UI side of things, I start with Bootstrap and only use the interaction and autocomplete widgets in jQuery UI. RequireJS takes care of managing modularization and dependency management. Everything else is pulled from one of the ecosystems surrounding those main libraries and adapted to play well with each other. Most of the glue code I have written is related to streamlining the two-way bindings with form controls and the data sources. Its probably the greatest weakness of Backbone, and although the community has some solutions, it still required some work to fill the gap and create something that worked within the context of applications I need to build.

These MVC libraries are all entering their fourth year of existence. At this point, we can probably call them mature and reasonably stable. The question is, if technology keeps changing at its historical pace, how relevant are these libraries in building the future of the web? What are the latest innovations in building better technologies for developers to enable writing leaner, more efficient code that creates a rich user experience that performs well across both desktop and mobile devices? We'll always discover better ways to do the same thing and be faced with finding new solutions as technology changes. I'd expect these established libraries to be capable of adapting to these changes for some time to come. Maybe in another 10 years we'll look back and say that these solutions are out dated and no longer represent the cutting edge, defacto standard developers turn to when building applications.

Monday, April 28, 2014

A Basic Star Rating Bar jQuery Widget

The first web-based rating system I remember using was provided by Netflix when picking movies to watch. I can remember inspecting the HTML to learn how they built it. At the time, it seemed like an amazing trick given the available browser technology. Today, a rating bar UI widget is pretty common place. Whether you build your own or pick from the pool of existing options depends on your needs. Interested in what was out there, I did some quick research to see what existed related to libraries I already work with like Bootstrap and jQuery UI. On the Bootstrap GitHub issue log, an external project was recommended in the discussion for those interesting in an implementation. I also found there's a plan to build this type of widget into jQuery UI and found a project that already provides such an implementation.

Looking through these projects, it became evident that they are a bit larger than I might really need. I was curious how little code I could write to make a very simple rating bar that would work in a variety of situations. If its small enough, it costs very little in the way of bandwidth and would be easy to extend and adapt to other use cases. The final product I built is about 120 lines of code (both JS and CSS) with comments and blank lines. Follow along through this post to see how I got there. Not interested in how I built it? Then scroll to the end for a jsFiddle demo and links to the final code.

Monday, April 21, 2014

Using CSS3 Transitions to Draw a User's Attention to Change

I've been pondering how to draw a user's attention to a specific area of the page for a little while. I have a application that displays a wealth of information on the screen and receives real-time updates over a Socket.IO connection. The data isn't sorted by recent activity and the user is not initiating the reload of the data so how do you guide a user's eye to something that is currently important? Momentarily highlighting the changed area in color may be a good way to approach the problem. However, I found that it was not always obvious, especially, when color was already being utilized in several other ways to highlight importance. What I really wanted was everything else to fade out a bit to single out the updated item and, to emphasize the change more, apply some kind of effect to that item (color, animation, etc).

As a simple demonstration of what I'm trying to achieve, the following example organizing several content boxes of information. Each item is selected randomly to receive an "update" which simply changes the text and resets the time-since-last-updated counter. A timer generates consistent events and initiates the updating logic:

Sunday, April 13, 2014

Newline Madness: Justified HTML Elements Revisited

A little while ago, I wrote about my fun trying to create evenly spaced, rotated labels. As I pointed out in the post, the evenly space portion was based on a perfectly justified grid technique I found. It solved part of my problem, however, I did find that IE gave me some problems unless I added text-justify: distributed along side the text-lign: justify in the styles. With those minor changes, everything worked fine in my development environment. However, once I tried packaging up my app for production, the solution stopped working.

A little background is necessary to understand what happened. The application has a pile of template HTML which I wanted to compress down as much as possible so I added the grunt htmlmin task to my build process so the extra white space and line breaks where removed from the markup. It turns out that this spacing trick relied on the invisible text nodes created by those line breaks and indentation I used to keep the markup readable during development. Once they weren't there, the content collapsed as if the justification was not even applied.

Sunday, April 6, 2014

HTML Positioning: The Curious Case of Centering the Unknown

It would seem like something as simple as centering an object perfectly, both horizontally and vertically, inside a container should be a basic capability of HTML/CSS. However, I've found that the less you know about your surroundings, the more difficult it gets to accomplish that goal. When you're trying to build something that is fluid and adapts to the available browser size, it becomes challenging to pull off such a simple feat. The best solution I've found that works in the most browsers is using a ghost pseudo-element to allow an element to vertically align inside its parent:

.parent-ghost {
  text-align: center;
  border: 3px solid #555;
  height: 300px;
  width: 70%;
}

.parent-ghost:before {
  content: '';
  display: inline-block;
  height: 100%;
  vertical-align: middle;
  margin-right: -0.25em; /* Adjusts for spacing */
}

.child-ghost {
  display: inline-block;
  vertical-align: middle;
  width: 20%;
  height: 20%;
  background-color: #f00;
}




Of course, this does not work in IE7 or older which means you either need to fallback to using tables or decide if the current market usage is actually worth the effort (As of February 2014, IE7 shows 0.0%).

Now, if you're willing to ignore 7% of the browser market, you can make things really simple by using the Flexbox Layout module. Although pretty recent, all modern browsers do support it. However, your IE users are going to have to use IE11 to take advantage of it:

.parent-flex {
  display: flex;
  height: 300px;
  width: 70%;
  border: 3px solid #555;
}

.child-flex {
  width: 20%;
  height: 20%;
  margin: auto;
  background-color: #f00;
}





That's a very simple example of how using Flexbox makes laying out content easier. If you haven't tinkered with it, take a look at the CSS-Tricks guide for an introduction. However, once you start using it, you may never want to go back to the old way. I've have a basic understanding of what features Flexbox offers. Since its been only recently implemented, it hasn't been a priority for me to start using it for all my layout problems. For now, I'll appreciate that the time will come when it will be in common use but will rely on the old bag-of-tricks to layout pages for a bit longer.

Now, my favorite trick to centering objects is to use a CSS3 Transform to translate the object back 50% of its height and width (for simplicity, I've left out the vendor prefix variations):

.parent-translate {
  overflow: hidden;
  height: 300px;
  width: 70%;
  border: 3px solid #555;
  position: relative;
}

.child-translate {
  position: absolute;
  width: 20%;
  height: 20%;
  background-color: #f00;

  top: 50%;
  left: 50%;

  transform: translateX(-50%) translateY(-50%);
  /* Split because IE10 won't honor the percentage in translate(-50%, -50%) */
}





This method is not supported in IE8, so according to the market stats, you'll lose 2.7% of your audience (well, they'll simply see a box with its top/left corner centered in the parent). However, the reason I tend to use this method is because I generally attach a transition on the element to animate it into position. Since its already absolutely positioned, I can animate the top property to slide it into view:

.slide {
  top: -50%;

  transition: top 1s;
}

.slide.in {
  top: 50%;
}


Attach a little JS to trigger the action:

   $( '#slide-in' ).click( function() { $( '.slide' ).addClass( 'in' ); } );
   $( '#slide-out' ).click( function() { $( '.slide' ).removeClass( 'in' ); } );




Now the transition won't work in IE9 so we've lost another 2% of our users. Again, its not a complete failure - the box still toggles into view - it just doesn't slide up or down.

Lately, I've come to the conclusion that the current features available in HTML5/CSS3 greatly ease the effort required to create great content and user experiences. I have a hard time justifying not leveraging these technologies because a small segment of the Internet is stuck in the past. I realize this is not usually the individual user's fault (corporate policy, etc). In the end, you have to pick what is suitable for your audience. I just prefer to attempt to nudge everyone forward or at least be ready for the eventual switch. Its nice to see that the browser is evolving to a better place that enables developers to spend less time positioning content and more time building it.

Monday, March 31, 2014

Using MomentJS to Extend the jQuery UI TimePicker Spinner Widget

In my last post, I used several jQuery UI Spinner widgets to create a Time Picker widget. At the time, I was more interested in making the widgets work together than providing a robust getter/setter function. So I cobbled together a simple string parser to split up the time value and set each spinner to the desired value. Additionally, the widget assumed the input format was a 12-hour clock which is not always desirable. So, in this post, I'll add some more features to provide more flexibility and options related to the format. While I don't like adding too many external dependencies, the MomentJS library does everything I need plus a pile of other great features. I generally use it in every project that has any kind of date/time display, manipulation, entry, etc. That said, I made an effort to gracefully fallback to the simple string method I originally wrote for anyone who doesn't want the extra 9Kb of gzip'd Javascript loading.

To review, the current TimePicker has this implementation for getting the current value of the widget:


      _value: function() {
         var hour = this.$hour.val(),
             min = this.$minute.val(),
             ampm = this.$ampm.val();

         return hour + ':' + min + ' ' + ampm;
      }



And this chunk of code handles parsing an incoming value and setting each spinner:


      _parse: function( val ) {
         var parts = val.split( /[: ]/ ),
             hour, min, ampm;

         if ( parts.length < 2 ) return;

         hour = parts[0];
         min = parts[1];
         ampm = parts[2];

         this.$hour.paddedspinner( 'value', +hour );
         this.$minute.paddedspinner( 'value', +min );
         this.$ampm.ampmspinner( 'value', ampm == 'AM' ? 0 : 1 );

      }



The goal is to retain those sections of code but 1) handle a 24-hour clock and 2) detect Moment and use it to both parse the incoming value or create a Moment instance to return the current value of the widget. Before doing that, we need to know the format to use for the widget. I decided to use a format string that aligns with Moment to determine whether to use a 12 or 24 hour clock:

Saturday, March 22, 2014

Build a Time Picker using jQuery UI Spinner Widgets

I've tried several methods of allowing a user to enter time. I prefer solutions that ensure the user can not enter an invalid time. A free-form text box with a mask will work to guide the entry but the validation is more complicated - especially if you're trying to restrict the entry to specific time intervals (ie every 5 minutes). In situations where there is an allowed time interval, I provided a single drop-down with all the valid selections. However, for small time intervals, the select box becomes large and difficult to navigate. In those cases, I've used several select boxes, each representing a different component of the time. The jQuery UI Spinner demo uses a single field to allow spinning through components of the entered time. However, there is no guided free-form entry so you'll have to validate the entry and ensure it is actually correct. I also found a time picker that extends the jQuery UI Datepicker widget. It has a lot of options for controlling the input a user interacts with while entering time. When creating a widget to enter different time components, I prefer to keep the input visually similar to how time is actually displayed. I think its more intuitive and natural since the whole value can be seen in its normal form. Given that, I decided to assemble several spinners to create a time selection widget. While the widget I present here will work, it will not have many features. However, there are three aspects of the functionality I'd like to focus on providing:

  • A value method to get/set the time in the widget. Since the value is split across three spinners, it needs to be parsed and formatted appropriately
  • Minimally, the minutes should be zero padded for anything less than 10 and you should only be able to switch between AM and PM
  • When you reach the limit of the hours or minutes, roll over to the beginning/end and change the other spinners. For example, if you go from 11 to 12, switch the AM/PM choice to allow you to move through the entire 24 hour day without having to change both fields individually.


Monday, March 10, 2014

Drawing Shapes with CSS3 Box Shadow

When I first looked at the box shadow style, I did not really give much thought to the fact you could specify multiple shadows. At least not until I stumbled upon this pixel art creator which used that ability to build pixel art in a single tag. So, of course I drew something and started thinking what else I could do with this interesting property. It meant that I could add more complex shapes to my content where I might otherwise have to use a graphic. I started with a comment bubble:







Which scaled down works nicely as an icon:



And the CSS to create it is probably smaller than an image or font file:

<div style="
  height: 1px; width: 1px; 
  box-shadow: 2px 3px 0 #3498DB,3px 3px 0 #3498DB,
              4px 3px 0 #3498DB,5px 3px 0 #3498DB,
              6px 3px 0 #3498DB,7px 3px 0 #3498DB,
              8px 3px 0 #3498DB,9px 3px 0 #3498DB,
              10px 3px 0 #3498DB,11px 3px 0 #3498DB,
              1px 4px 0 #3498DB,2px 4px 0 #3498DB,
              3px 4px 0 #3498DB,4px 4px 0 #3498DB,
              5px 4px 0 #3498DB,6px 4px 0 #3498DB,
              7px 4px 0 #3498DB,8px 4px 0 #3498DB,
              9px 4px 0 #3498DB,10px 4px 0 #3498DB,
              11px 4px 0 #3498DB,12px 4px 0 #3498DB,
              1px 5px 0 #3498DB,2px 5px 0 #3498DB,
              3px 5px 0 #3498DB,4px 5px 0 #3498DB,
              11px 5px 0 #3498DB,12px 5px 0 #3498DB,
              1px 6px 0 #3498DB,2px 6px 0 #3498DB,
              3px 6px 0 #3498DB,4px 6px 0 #3498DB,
              5px 6px 0 #3498DB,6px 6px 0 #3498DB,
              7px 6px 0 #3498DB,8px 6px 0 #3498DB,
              9px 6px 0 #3498DB,10px 6px 0 #3498DB,
              11px 6px 0 #3498DB,12px 6px 0 #3498DB,
              1px 7px 0 #3498DB,2px 7px 0 #3498DB,
              9px 7px 0 #3498DB,10px 7px 0 #3498DB,
              11px 7px 0 #3498DB,12px 7px 0 #3498DB,
              1px 8px 0 #3498DB,2px 8px 0 #3498DB,
              3px 8px 0 #3498DB,4px 8px 0 #3498DB,
              5px 8px 0 #3498DB,6px 8px 0 #3498DB,
              7px 8px 0 #3498DB,8px 8px 0 #3498DB,
              9px 8px 0 #3498DB,10px 8px 0 #3498DB,
              11px 8px 0 #3498DB,12px 8px 0 #3498DB,
              1px 9px 0 #3498DB,2px 9px 0 #3498DB,
              3px 9px 0 #3498DB,12px 9px 0 #3498DB,
              2px 10px 0 #3498DB,3px 10px 0 #3498DB,
              4px 10px 0 #3498DB,5px 10px 0 #3498DB,
              6px 10px 0 #3498DB,7px 10px 0 #3498DB,
              8px 10px 0 #3498DB,9px 10px 0 #3498DB,
              10px 10px 0 #3498DB,11px 10px 0 #3498DB,
              3px 11px 0 #3498DB,4px 11px 0 #3498DB,
              3px 12px 0 #3498DB;"
></div>


And then it seemed only natural to make a spinner:




@keyframes spin {
    from { transform: translate3d(0, 0, 0) rotate(0deg); }
    to { transform: translate3d(0, 0, 0) rotate(360deg); }
}

.spinner {
    height: 1px; 
    width: 1px;
    transform-origin: 14px 14px;
    animation-name: spin; 
    animation-duration: 1s;
    animation-iteration-count: infinite; 
    animation-timing-function: linear;    
}

.spinner.balls {
    box-shadow: 
       13px 2px 0 #8F8588,14px 2px 0 #8F8588,12px 3px 0 #8F8588,
       13px 3px 0 #8F8588,14px 3px 0 #8F8588,15px 3px 0 #8F8588,
       12px 4px 0 #8F8588,13px 4px 0 #8F8588,14px 4px 0 #8F8588,
       15px 4px 0 #8F8588,6px 5px 0 #8F8588,7px 5px 0 #8F8588,
       13px 5px 0 #8F8588,14px 5px 0 #8F8588,20px 5px 0 #8F8588,
       21px 5px 0 #8F8588,5px 6px 0 #8F8588,6px 6px 0 #8F8588,
       7px 6px 0 #8F8588,8px 6px 0 #8F8588,19px 6px 0 #8F8588,
       20px 6px 0 #8F8588,21px 6px 0 #8F8588,22px 6px 0 #8F8588,
       5px 7px 0 #8F8588,6px 7px 0 #8F8588,7px 7px 0 #8F8588,
       8px 7px 0 #8F8588,19px 7px 0 #8F8588,20px 7px 0 #8F8588,
       21px 7px 0 #8F8588,22px 7px 0 #8F8588,6px 8px 0 #8F8588,
       7px 8px 0 #8F8588,20px 8px 0 #8F8588,21px 8px 0 #8F8588,
       3px 12px 0 #8F8588,4px 12px 0 #8F8588,23px 12px 0 #8F8588,
       24px 12px 0 #8F8588,2px 13px 0 #8F8588,3px 13px 0 #8F8588,
       4px 13px 0 #8F8588,5px 13px 0 #8F8588,22px 13px 0 #8F8588,
       23px 13px 0 #8F8588,24px 13px 0 #8F8588,25px 13px 0 #8F8588,
       2px 14px 0 #8F8588,3px 14px 0 #8F8588,4px 14px 0 #8F8588,
       5px 14px 0 #8F8588,22px 14px 0 #8F8588,23px 14px 0 #8F8588,
       24px 14px 0 #8F8588,25px 14px 0 #8F8588,3px 15px 0 #8F8588,
       4px 15px 0 #8F8588,23px 15px 0 #8F8588,24px 15px 0 #8F8588,
       6px 19px 0 #8F8588,7px 19px 0 #8F8588,20px 19px 0 #8F8588,
       21px 19px 0 #8F8588,5px 20px 0 #8F8588,6px 20px 0 #8F8588,
       7px 20px 0 #8F8588,8px 20px 0 #8F8588,19px 20px 0 #8F8588,
       20px 20px 0 #8F8588,21px 20px 0 #8F8588,22px 20px 0 #8F8588,
       5px 21px 0 #8F8588,6px 21px 0 #8F8588,7px 21px 0 #8F8588,
       8px 21px 0 #8F8588,19px 21px 0 #8F8588,20px 21px 0 #8F8588,
       21px 21px 0 #8F8588,22px 21px 0 #8F8588,6px 22px 0 #8F8588,
       7px 22px 0 #8F8588,13px 22px 0 #8F8588,14px 22px 0 #8F8588,
       20px 22px 0 #8F8588,21px 22px 0 #8F8588,12px 23px 0 #8F8588,
       13px 23px 0 #8F8588,14px 23px 0 #8F8588,15px 23px 0 #8F8588,
       12px 24px 0 #8F8588,13px 24px 0 #8F8588,14px 24px 0 #8F8588,
       15px 24px 0 #8F8588,13px 25px 0 #8F8588,14px 25px 0 #8F8588;
}


Its important to shift the transform origin to match the final size of your box shadow "grid". The DIV is only 1 pixel high and wide so the point of rotation is in the top, left corner of the box shadow area.

While probably something that should be used in moderation, its still a fun trick that can come in handy in certain situations.

Wednesday, March 5, 2014

Customize the jQuery UI AutoComplete Drop Down Select Menu

When attempting to customize the jQuery UI Autocomplete widget's select box markup to match a Bootstrap drop down menu, I found that the hooks available are not part of the normal options hash. It seemed a little odd to provide this functionality in the form of a plugin extension and the documentation doesn't provide quite enough context for someone less familiar with the internals of the core widget library to actually implement the hook. The primary functions of interest are _renderItem and _renderMenu. Since they are prefixed with the "_", the widget factory will hide these methods from the plugin. So, in the documentation, you can see there is a method "close" which is called through the plugin on the target element:

   $( '#myac' ).autocomplete( 'close' )


however, you can't call _renderMenu in the same way:

   $( '#myac' ).autocomplete( '_renderMenu' )


That will throw an error. However, you can access anything in the widget instance object via $.data:

   var ac_inst = $( '#myac' ).data( 'ui-autocomplete' );


Now you can do fancy things with this object like change the behavior of _renderMenu:

Monday, February 17, 2014

Buidling Ranges of Date/Time Intervals in Ruby

There are a lot of features that define a good programming language. One of them has to be how it enables a developer to represent and manipulate date and time values. As usual, Ruby has a class (actually several) that abstract the representation of date/time and provide a nice set of methods to manipulate it. Adding in Active Support provides even more functionality. My latest challenge was to divide a period of time into a series of even intervals. Using the built in methods seemed like the right path but I quickly experienced some difficulties:

> DateTime.now.step( 1.week.from_now ).to_a
=> []


After a closer examination of the documentation and I realize that the limit needed to be a Date object, not DateTime. As it turns out, this mix-and-match typing has caused me the most issues when working with dates and times in Ruby. Either you get an error or the results are not what you expected. Based on the documentation on the step function, it should default to an interval of one which I assumed meant one day. Once I switched to the right type, that's what happened:

> DateTime.now.step( 1.week.from_now.to_date ).to_a
=> [Sat, 15 Feb 2014 07:52:23 -1000, 
    Sun, 16 Feb 2014 07:52:23 -1000, 
    Mon, 17 Feb 2014 07:52:23 -1000, 
    Tue, 18 Feb 2014 07:52:23 -1000, 
    Wed, 19 Feb 2014 07:52:23 -1000, 
    Thu, 20 Feb 2014 07:52:23 -1000, 
    Fri, 21 Feb 2014 07:52:23 -1000]


So, what if you want a different time interval? Active Support provides a convenient way to express time, but its not the expected type that the step function wants:

> DateTime.now.step( 1.month.from_now.to_date, 1.week ).to_a
TypeError: expected numeric
    (ripl):40:in `step'
    (ripl):40:in `each'
    (ripl):40:in `to_a'
    (ripl):40:in `
'


However, even converting the type still doesn't make it work as expected:

> DateTime.now.step( 1.month.from_now.to_date, 1.week.to_i ).to_a
=> [Sat, 15 Feb 2014 07:54:36 -1000]


Remembering that time is stored internally as seconds made me realize that the number being passed was seconds, not days so I added some math to the process:

>> DateTime.now.step( 1.month.from_now.to_date, 1.week / 1.day ).to_a
=> [Sat, 15 Feb 2014 07:55:04 -1000, 
    Sat, 22 Feb 2014 07:55:04 -1000, 
    Sat, 01 Mar 2014 07:55:04 -1000, 
    Sat, 08 Mar 2014 07:55:04 -1000]


Now, that enables me to work with intervals over days. But what if I want to create interval ranges during a day in seconds, minutes, or hours? When I try to divide a time value by 1.day, the output doesn't make sense:
>> ( DateTime.now..1.hour.from_now ).step( 12.hour.to_f / 1.day.to_f ).to_a.length
=> 7201


I should get an empty array since I want to step every 12 hours over a 1 hour range. Instead, I get 7201 numbers (not even dates). It appears the Date step function functionality wasn't going to work, but the Range type also has a step function and the above expression can be represented as a Range:

>> ( DateTime.now..1.month.from_now ).step( 1.week / 1.day ).to_a


Which, when coupled with converting to the base representation of time (ie seconds), we can simply work with numbers to build our ranges:

>> ( DateTime.now.to_i..1.hour.from_now.to_i ).step( 10.minutes ).to_a
=> [1392471205, 1392471805, 1392472405, 1392473005, 1392473605, 1392474205, 1392474805]


And instead of leaving them as numbers, we can switch them back to a DateTime object via the Time::at class method:


>> ( DateTime.now.to_i..1.hour.from_now.to_i ).step( 10.minutes ).
              map{ |t| Time.at( t ).to_datetime }

=> [Sun, 16 Feb 2014 07:02:54 -0600, 
    Sun, 16 Feb 2014 07:12:54 -0600, 
    Sun, 16 Feb 2014 07:22:54 -0600, 
    Sun, 16 Feb 2014 07:32:54 -0600, 
    Sun, 16 Feb 2014 07:42:54 -0600, 
    Sun, 16 Feb 2014 07:52:54 -0600, 
    Sun, 16 Feb 2014 08:02:54 -0600]


Unfortunately, we lose some information by switching types like the time zone. Once you convert to a numeric and then back to a Date object, you'll be back in local time, which may not be the zone you started in. If its important to keep that, you'll have to store it before iterating and then restore it on each step:


>> from_tm = Time.now.localtime('-08:00')
>> to_tm = from_tm + 1.hour
>> tm_zone = from_tm.gmt_offset

>> ( from_tm.to_i..to_tm.to_i ).step( 10.minutes ).
            map{ |t| Time.at( t ).localtime( tm_zone ).to_datetime }

=> [Sun, 16 Feb 2014 04:01:46 -0800, 
    Sun, 16 Feb 2014 04:11:46 -0800, 
    Sun, 16 Feb 2014 04:21:46 -0800, 
    Sun, 16 Feb 2014 04:31:46 -0800, 
    Sun, 16 Feb 2014 04:41:46 -0800, 
    Sun, 16 Feb 2014 04:51:46 -0800, 
    Sun, 16 Feb 2014 05:01:46 -0800]



With a little experimenting, you can very quickly express a range of time and step through a certain intervals between those points. Instead of building an array, you might perform a series of more complex operations on the generated values. Maybe the biggest issue with some of these examples is the loss of abstraction of the representation of the date/time. The last set of examples for creating time ranges requires you to toss out the DateTime object and directly manipulate an integer representation of the time. It would be nice if the DateTime#step function could take any type of date object as a limit and and properly apply steps of less than a day without coercing the types of any inputs. Depending on your needs, it might make sense to build a few utility functions or classes to assist with these types of operations.

Sunday, February 9, 2014

Backbone Sync: Customizing JSON Payload Options for Persistence Operations

Backbone Models provide a reasonably light-weight layer over raw AJAX calls to make it easier to define data objects that are acquired and persisted using RESTful services. As I've been working Backbone into more complex projects, I've noticed a pattern emerging that requires some minor tweaks to the default persisting behavior provided by the library. Fortunately, Backbone is very flexible and augmenting these features is not exceptionally difficult. Let's begin with a little context on a specific problem. Consider a simple model:


var myModel = Backbone.Model.extend({
   
   defaults: {
      id: null,
      color: 'blue',
      size: 'big',      
   },

   ...
});



A Model.fetch() call may return more data than what is specified in the defaults like created_on and created_by, where the former is a date stamp set on the server side when the record was originally added and the latter is a person, again, set server-side based on the logged in user. The contents of the created_by attribute could be a hash containing additional details about the user beyond just a name or ID value. These extra fields are useful for rendering information on the screen, but are not required to persist the model back to the server. In the case of the created_by attribute, packing the extra detail into the read operation saves a round trip to the server to fetch the related record. However, the default behavior when Backbone saves the data is to include all the attributes in the model. On more complex models, this can result in fairly large PUT payloads. Not only could they become relatively large, they also become difficult to debug since there is so much extra data that will simply be ignored by the server. My goal is to try to slim down the payload being sent back to the server even if the read operation pulled some extra data.

Sunday, January 26, 2014

Resizing Images in the Browser using an HTML Canvas

Nothing pleases me more than not having to upload an image from someone's computer and use my server to resize the image. Being able to use the browser to acquire the file, resize it to something reasonable, and only upload it after the user previews it and decides its correct saves both bandwidth and server resources. However, as great as it sounds, there's always a catch. On the server-side, you can control the resources and processes used to resize the image. On the client-side, you have less control. Different resources and browsers limit your ability to use any method you can conjure up to perform the resize operation. Users tend to be fickle about their browser locking up or, worse, crashing when they attempt to open an unusually large 15Mb JPEG image of their dog, Sammy. Even if you can avoid that problem, you may find the resize of the image looks undesirable due to how the browser resampled it.

The easiest way to resize an image is to draw it into a smaller canvas object and then pull the data URL from the canvas with the resized image:


   var baseImg = $( '#base' )[0],
       outImg = $ctr.find( '.resize1' )[0],
       canvas, context;

   canvas = document.createElement( 'canvas' );
   canvas.width = baseImg.width;
   canvas.height = baseImg.height;
   context = canvas.getContext( '2d' );
   context.drawImage( baseImg, 0, 0, baseImg.width, baseImg.height );

   outImg.src = canvas.toDataURL();




Below is a test image with a resolution of 1024 X 768 pixels and a file size of about 2.4 Mb. I placed it in an image tag with a max-height of 400px which will force the browser to scale the image. When those properties are queried in the resize operation above, they report the size of the rendered image on the screen and not the original size. Because of this, the resulting canvas image will then be sized at the desired 400 X 300 pixels and the new file size will be 78 Kb:



Sunday, January 19, 2014

RequireJS Optimization and Dynamic Loading of Shimmed Libraries

I've written a few posts about building module web application using RequireJS as a centerpiece to manage dependencies and help reduce load times. One challenge you encounter when using this design strategy is that not every library you need to use in your application is RequireJS aware. Fortunately, this is accounted for in the RequireJS configuration options in the form of a "shim". However, as I learned when working out all the details of my release life-cycle, there are some caveats you need to address when working with the RequireJS optimizer and dynamically loading shimmed libraries. Before addressing those issues, let me create some context by explaining how I setup my application for development and ready it for release.

Sunday, January 5, 2014

CSS Rotated Text: Parent Dimensions and Spacing Issues

Rotating text with CSS seemed like an great solution to my space problem. I have a table of narrow columns but need labels that will not fit in that space. Rotating them 90 degrees would fix the problem. However, fixing one problem only exposed another issue. The following examples will use this block of HTML to define the content for the columns that need to be rotated.


  <ul class="list-unstyled">
      <li><span>A column label</span></li>
      <li><span>Short</span></li>
      <li><span>Much longer than the last</span></li>
      <li><span>Another label</span></li>
      <li><span>The final column</span></li>
  </ul>



Without any rotation, the markup renders like this:

  • A column label
  • Short
  • Much longer than the last
  • Another label
  • The final column


Now, let's try to apply a transform to rotate the text.