Adding Responsive Design Features to an Existing Webapp Part 2: Touchscreens and Tables

Continues on from Part 1

Adapting to touchscreens

Responsive design
Our main navigation uses drop down menus. These are not compatible with touchscreen devices, and also contain links to pages that were not desirable on smaller mobile devices. The navigation layouts would also need alterations to fit properly.
Firstly, we need the ability to target touchscreen devices only. Media queries are not helpful here, as a desktop browser opened in a narrow window would be indistinguishable from a mobile browser at similar width.
So I used some Javascript to add a class to the page body if the device being used has a touchscreen. At the same time we can show or hide certain elements depending on the device having a touch screen.
Using Prototype JS,

function isTouchable() { 
   try {  
      document.createEvent('TouchEvent');  
      return true;  
   } catch (e) {  
      return false;  
   }  
}

if (isTouchable() 
      || navigator.userAgent.match(/(iPhone|iPod|iPad)/) 
      || navigator.userAgent.match(/BlackBerry/) 
      || navigator.userAgent.match(/Android/)) {
   $$('body')[0].addClassName('touchable');
   $$('.touchable-show').each(function(elem){
      $(elem).removeClassName('is-hidden');
   });
   $$('.touchable-hide').each(function(elem){
      $(elem).addClassName('is-hidden');
   });
   window.scrollTo(0, 1);
}

Now we can add some css that targets touch screens only.
Removing the drop down parts of the navigation was not a problem on the sites that I was working on because the main headings of the menus all link to a contents page that itself contains all of the links from the drop down menu. If unique links were present, I would look for another way to present them. One possibility is the use of an html select in place of navigation elements.

Responsive tables

The major remaining barrier to a useable mobile experience now becomes wide tables. A table that has more than a few columns will usually display fine on a full width desktop browser, but quickly becomes too wide for narrow displays.
There are different possible solutions to this issue, none quite perfect.

  1. Let the table expand beyond the page borders. The user can scroll around the whole area. This also means that the page gets rendered incorrectly as it extends to contain the table.
  2. Put the table inside a fixed width container, and let the table be swiped horizontally to view different columns. Good but useful data may be hidden, and it is difficult to ensure that the user knows about this functionality.
  3. Remove some of the columns for mobile. This way the most important information can be displayed. Not so good if importance varies per user.
  4. Adapt the table to display information in more vertical way.
    name height weight sex age wpm
    Junior 158cm 54Kg M 12 18
    Senior 175cm 83Kg M 41 33

    becomes

    Junior
    height: 158cm
    Weight: 54Kg
    Sex: M
    age:12
    wpm:18
    Senior
    height: 175cm
    Weight: 83Kg
    Sex: M
    age: 41
    wpm: 33

    This is good, but difficult to compare values and larger tables can become very long.

After consideration, I chose to attempt a combination of 2 and 3, with controls. I wanted to display selected columns depending on data priorities and screen width. But also to allow the user to show and hide columns so that all of the columns in the full table are accessible if required. And in case of the table becoming wider than the available space when columns are added, I wanted the table to be scrollable within a fixed size container.
Again using Prototype JS,

/**
 * Shows selected table columns on smaller width browsers.
 * For tables with headings on the first row
 * Adds toggles for the user to show / hide columns as required.
 * To use, place the table into a parent element with class 'responsive-table'
 * add attributes for column preference on smaller screens.
 * 'data-persist' : always shown.
 * 'data-pref1' : shown on load, no matter what device.
 * 'data-pref2' : shown if width >= 480
 * 'data-pref3' : shown if width >= 768
 * All columns shown for width >= 960
 * eg: 
 * <div class='responsive-table' data-persist='1' data-pref1='2,4' data-pref2='3' data-pref3='7'>
 *    <table>...</table>
 * </div>
 **/

$$('.responsive-table').each(function(tc) { 
   var tbl = tc.select('table')[0],
   pref1Cols = [],
   pref2Cols = [],
   pref3Cols = [],
   persistentCols = [],
   allCols = true;
   shownCols = [],
   options = new Element('div', {'class': 'table-view-controls' }).insert('Show: '),
   viewWidth = document.viewport.getDimensions().width;
   if (!tbl) { return; }
   if(viewWidth < 960) { 
      if (tc.readAttribute('data-persist')) { 
         persistentCols = tc.readAttribute('data-persist').split(',');
      }
      if (tc.readAttribute('data-pref1')) { 
         pref1Cols = tc.readAttribute('data-pref1').split(',');
      }
      if (tc.readAttribute('data-pref2')) { 
         pref2Cols = tc.readAttribute('data-pref2').split(',');
      }
      if (tc.readAttribute('data-pref3')) { 
         pref3Cols = tc.readAttribute('data-pref3').split(',');
      } 
      shownCols = persistentCols.concat(pref1Cols); 
      allCols = false;
      if(viewWidth >= 480) {
         shownCols = shownCols.concat(pref2Cols);
      }
      if (viewWidth >= 768) {
         shownCols = shownCols.concat(pref3Cols);
      }
      $$('.responsive-table tr:first-child th').each(function(th, index) { 
         if(persistentCols.indexOf('' +  (index + 1)) > -1) { return; } 
            var toggler = new Element('span', {'class': 'column-toggle' }); 
            options.insert(toggler);
            toggler.insert(th.innerHTML);
            if (allCols || shownCols.indexOf('' +  (index + 1)) > -1) {
               toggler.addClassName('column-showing');
            } else {
               $$('.responsive-table tr > *:nth-child(' + (index + 1) + ')').each(function(cell) {
                  cell.setStyle({ display: 'none' });
               });
            } 
            toggler.observe('click', function(event) {
            var disp;
            if(toggler.hasClassName('column-showing')) {
               toggler.removeClassName('column-showing');
               disp = 'none';
            } else {
               toggler.addClassName('column-showing');
               disp = 'table-cell';
            }
            $$('.responsive-table tr > *:nth-child(' + (index + 1) + ')').each(function(cell) {
               cell.setStyle({ display: disp });
            }); 
         }); 
      });
      $(tbl).insert({ before: options }); 
   } 
});

And the accompanying css:

.responsive-table {
   overflow-x: auto;
}
.table-view-controls {
   font-size: 0.9em;
}
.column-toggle {
   cursor: pointer;
   text-decoration: line-through;
   display: inline-block;
}
.column-toggle.column-showing {
   text-decoration: underline;
}

I am mostly happy with the result. It works as intended, and solves a lot of problems. Although the design could be improved.
Compare the full size version and the same table adjusted for a 320px browser:

Wait or Make Responsive Now?

Responsive design is obviously going to be better implemented as part of the whole development process from the beginning. For example, it would be far better to use a more recent grid system created with responsive design issues in mind. And more modular page structures would be easier to use dynamically. Designing for multiple devices concurrently adds complexity, but is necessary to achieve optimum user experiences across different platforms. I didn’t have the opportunity to work in this way this time,  so was prepared to make compromises with the interfaces. Further work would be best saved for the next iteration of the web application.
However, I do feel that I was able to make some useful changes across  the 6 web applications for a relatively small amount of work. Customers will now be able to access control panels more happily while away from their work machines, and potential customers might be just a little more interested in services that provide a readable mobile experience.
Less work could be done and still have beneficial effects. You could use media queries to make small changes:

  • Add padding to buttons for touch screen users
  • Change font sizes for different size displays
  • Adjust the body width to fit with simpler pages
  • Remove certain links or ads
  • provide an alternative to part of the web app that has performance issues for mobile

So if it will be a long time until the next iteration of your web application, and you think that improvements to the mobile interface could help your business, then adding at least some responsive design aspects now should be a consideration.

View the web applications discussed here:

http://25mail.st

http://25mail.st

http://2partsmagic.com

http://2partsmagic.com

http://bakop.com

http://bakop.com

http://inboxharmony.com

http://inboxharmony.com

http://pingability.com

http://pingability.com

http://zonomi.com

http://zonomi.com

For help making your web site responsive, or any other development work, contact 2 Parts Magic.

Bookmark and Share
This entry was posted in All and tagged , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">

What is 15 + 9 ?
Please leave these two fields as-is:
IMPORTANT! To be able to proceed, you need to solve the following simple math (so we know that you are a human) :-)