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">
<a href="#" class="small" data-value="option1" tabIndex="-1">
<input type="checkbox"/>&nbsp;Option 1
<a href="#" class="small" data-value="option2" tabIndex="-1">
<input type="checkbox"/>&nbsp;Option 2
<a href="#" class="small" data-value="option3" tabIndex="-1">
<input type="checkbox"/>&nbsp;Option 3
<a href="#" class="small" data-value="option4" tabIndex="-1">
<input type="checkbox"/>&nbsp;Option 4
<a href="#" class="small" data-value="option5" tabIndex="-1">
<input type="checkbox"/>&nbsp;Option 5
<a href="#" class="small" data-value="option6" tabIndex="-1">
<input type="checkbox"/>&nbsp;Option 6

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' ),

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


   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">

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.