How to Make Google More Accessible for Low-Vision Users with User Scripts

Make Google More Accessible for Low-Vision Users

Change Google's layout to make it easier for low-vision users to read.

As a class of disabilities, low-vision users are often ignored by accessibility experts. However, accessibility expert Joe Clark has recently published his research into the needs of web users with limited vision. He pioneered a technique known as the zoom layout: a special alternate style applied to a web page that specifically caters to low-vision users.

As I was learning about zoom layouts, it occurred to me that this would be a perfect application of Greasemonkey. (Actually, that thought occurs to me a lot these days.) This hack is my first attempt at transforming a site into a zoom layout.

You can read more about zoom layouts at http://www.alistapart.com/articles/lowvision/ and http://joeclark.org/atmedia/atmedia-NOTES-2.html.


The Code

This user script runs on several specific Google pages:

This hack is written to be cross-browser compatible. It works in Firefox with Greasemonkey, in Internet Explorer 6 for Windows with Turnabout, and in Opera 8 with its built-in support for User JavaScript. You can download Turnabout at http://reifysoft.com/turnabout.php, and Opera at http://www.opera.com.


Save the following user script as zoom-google.user.js:

 // ==UserScript==
 // @name  Zoom Google
 // @namespace http://diveintomark.org/projects/greasemonkey/
 // @description make Google more accessible to low-vision users
 // @include  http://www.google.tld/
 // @include  http://www.google.tld/?*
 // @include http://www.google.tld/webhp* 
 // @include http://www.google.tld/imghp*
 // @include http://www.google.tld/search*
 // @include http://images.google.tld/
 // @include http://images.google.tld/?*
 // @include http://images.google.tld/images*
 // ==/ UserScript==
 function addGlobalStyle(css) {
  var elmHead, elmStyle;
  elmHead = document.getElementsByTagName('head')[0];
  elmStyle = document.createElement('style');
  elmStyle.type = 'text/css';
  elmHead.appendChild(elmStyle);
  elmStyle.innerHTML = css;
 }
 function getElementsByClassName(sTag, sClassName) {
  sClassName = sClassName.toLowerCase( ) + ' ';
  var arElements = document.getElementsByTagName(sTag);
  var iMax = arElements.length;
  var arResults = new Array( );
  for (var i = 0; i < iMax; i++) {
   var elm = arElements[i];
   var sThisClassName = elm.className;
   if (!sThisClassName) { continue; }
   sThisClassName = sThisClassName.toLowerCase( ) + ' ';
   if (sThisClassName.indexOf(sClassName) != -1) {
    arResults.push(elm);
   } 
  }
  return arResults;
 }
 function removeFontTags( ) {
  // remove font tags
  var arFonts = document.getElementsByTagName('font');
  for (var i = arFonts.length - 1; i >= 0; i--) {
   var elmFont = arFonts[i];
   var elmSpan = document.createElement('span');
   elmSpan.innerHTML = elmFont.innerHTML;
   elmFont.parentNode.replaceChild(elmSpan, elmFont);
  }
 }
 function zoomStyle( ) {
  addGlobalStyle('body { margin: 30px; } \n' +
 'body, td { font-size: large ! important; } \n' +
 'html>body, html>body td { font-size: x-large ! important; } \n' +
 'body, div, td { background: navy ! important; ' +
  'color: white ! important; } \n' +
 'a:link { background: transparent ! important; ' +
  'color: yellow ! important; } \n' +
 'a:visited { background: transparent ! important; ' +
  'color: lime ! important; } \n' +
 'a.fl { background: transparent ! important; ' +
  'color: white ! important; } \n' +
 'input { font-size: large ! important; } \n' +
 'html>body input { font-size: x-large ! important; } \n' +
 '.g { width: auto ! important; } \n' +
 '.n a, .n .i { font-size: large ! important; } \n' +
 'html>body .n a, html.body .n .i { font-size: x-large ! important; } \n' +
 '.j { width: auto ! important; }');
 }
 function accHomePage( ) {
  // remove personalized header, if any
  var arTable = document.getElementsByTagName('table');
  for (var i = arTable.length - 1; i >= 0; i--) {
   var elmTable = arTable = ar
   var html = elmTable.innerHTML;
   if (/\/accounts\/Logout/.test(html)) {
    elmTable.parentNode.removeChild(elmTable);
   }
  }
  // simplify logo
  var arImages = document.getElementsByTagName('img');
  for (var i = arImages.length - 1; i >= 0; i--) {
   var elmLogo = arImages[i];
   if (elmLogo.alt) {
    var elmTextLogo = document.createElement('h1');
    elmTextLogo.style.fontSize = '400%';
    var sAlt = /Firefox/.test(elmLogo.alt) ? '' : elmLogo.alt;
    elmTextLogo.appendChild(document.createTextNode(sAlt));
    elmLogo.parentNode.replaceChild(elmTextLogo, elmLogo);
    var elmLink = elmTextLogo.parentNode;
    while (elmLink.nodeName != 'BODY' &&
    elmLink.nodeName != 'HTML' &&
    elmLink.nodeName != 'A') {
    elmLink = elmLink.parentNode;
    }
    elmLink.style.textDecoration = 'none';
   } else {
    elmLogo.parentNode.removeChild(elmLogo);
   }
  }
  // simplify search form
  if (document.forms.length) {
   var arTD = document.getElementsByTagName('td');
   for (var i = arTD.length - 1; i >= 0; i--) {
    var elmTD = arTD[i];
    if (/Advanced/.test(elmTD.innerHTML)) {
    elmTD.innerHTML = '';
    }
   }
  }
 }
 function accSearchResults( ) {
  // simplify logo
  var elmLogo = document.getElementsByTagName('img')[0];
  var elmTextLogo = document.createElement('h1');
  elmTextLogo.appendChild(document.createTextNode(' Google'));
  elmTextLogo.style.marginTop = '0.2em';
  elmTextLogo.style.marginRight = '0.3em';
  elmLogo.parentNode.replaceChild(elmTextLogo, elmLogo);
  elmTextLogo.parentNode.style.textDecoration = 'none';
  // simplify top form
  var elmAdvancedWrapper = document.getElementsByTagName('table')[3];
  var elmAdvanced = elmAdvancedWrapper.getElementsByTagName('td')[1];
  elmAdvanced.parentNode.removeChild(elmAdvanced);
  // remove "tip" if present
  var elmTip = document.getElementsByTagName('table')[7];
  if (/Tip/.test(elmTip.innerHTML)) {
   elmTip.parentNode.removeChild(elmTip);
  }
  // remove ads, if any
  var aw1 = document.getElementById('aw1');
  while (aw1) {
   var table = aw1.parentNode;
   while (table.nodeName != 'TABLE') {
    table = table.parentNode;
   }
   table.parentNode.removeChild(table);
   aw1 = document.getElementById('aw1');
  }
  var tpa1 = document.getElementById('tpa1');
  if (tpa1) {
   while (tpa1.nodeName != 'DIV' && tpa1.nodeName != 'P') {
    tpa1 = tpa1.parentNode;
   }
   tpa1.parentNode.removeChild(tpa1);
  }
  var tpa2 = document.getElementById('tpa2');
  if (tpa2) {
   while (tpa2.nodeName != 'DIV' && tpa2.nodeName != 'P') {
    tpa2 = tpa2.parentNode;
   }
   tpa2.parentNode.removeChild(tpa2);
  }
  addGlobalStyle('iframe[name="google_ads_frame"] { ' +
   'display: none ! important }');
  // simplify results count
  var elmDivider = document.getElementsByTagName('table')[5];
  elmDivider.parentNode.removeChild(elmDivider);
  var elmResultsContainer = document.getElementsByTagName('table')[5];
  var arTD = elmResultsContainer.getElementsByTagName('td');
  if (arTD.length > 1) {
   var sResults = arTD[1].textContent;
   var iParen = sResults.indexOf('(');
   if (iParen != -1) {
    sResults = sResults.substring(0, iParen);
   }
   var iDef = sResults.indexOf('[');
   if (iDef != -1) {
    sResults = sResults.substring(0, iDef);
   }
   var elmResults = document.createElement('h2');
   elmResults.appendChild(document.createTextNode(sResults));
   elmResultsContainer.parentNode.replaceChild(elmResults,
    elmResultsContainer);
  } else {
   elmResultsContainer.parentNode.removeChild(elmResultsContainer);
  }
  // make search results use real headers
  var arResults = getElementsByClassName('p', 'g');
  for (var i = arResults.length - 1; i >= 0; i--) {
   var elmResult = arResults[i];
   var arLink = elmResult.getElementsByTagName('a');
   if (!arLink.length) { continue; }
   var elmLink = arLink[0];
   var elmWrapper = document.createElement('div');
   var elmHeader = document.createElement('h3');
   elmHeader.style.margin = elmHeader.style.padding = 0;
   elmHeader.innerHTML = '<a href="' + elmlink.href + '">' +
    elmLink.innerHTML + '</a>';
   var elmContent = elmResult.cloneNode(true);
   elmContent.innerHTML = elmContent.innerHTML.replace(/<nobr>/g, '');
   arLink = elmContent.getElementsByTagName('a');
   if (!arLink.length) { continue; }
   elmLink = arLink[0];
   elmContent.removeChild(elmLink);
   elmContent.style.marginTop = 0;
   elmWrapper.appendChild(elmHeader);
   elmWrapper.appendChild(elmContent);
   elmResult.parentNode.replaceChild(elmWrapper, elmResult);
  }
  // simplify next page link
  var arFont = document.getElementsByTagName('font');
  for (var i = arFont.length - 1; i >= 0; i--) {
   var elmFont = arFont[i];
  var html = elmFont.innerHTML;
  if (/Result\&nbsp\;Page\:/.test(html)) {
   var elmTable = elmFont.parentNode; 
   while (elmTable.nodeName != 'TABLE') {
    elmTable = elmTable = elm
   }
   var arTD = elmTable.getElementsByTagName('td');
   if (arTD.length) {
    var elmTD = arTD[arTD.length - 1];
    var arNext = elmTD.getElementsByTagName('a');
    if (arNext.length) {
    var elmNext = arNext[0];
    var elmTextNext = document.createElement('center');
    elmTextNext.innerHTML = '<p style="font-size: ' + 
    'xx-large; margin-bottom: 4em;">b><a href="' +
    elmnext.href + '">More Results  ' +
    '&rarr;</a></b></p>';
    elmTable.parentNode.replaceChild(elmTextNext,  
    elmTable);
    }
   }
   break;
  }
 }
 // remove bottom ads
 var arCenter = document.getElementsByTagName('center');
 if (arCenter.length > 1) {
  var elmCenter = arCenter[1];
  elmCenter.parentNode.removeChild(elmCenter);
  elmCenter = arCenter[0];
  for (var i = 0; i < 4; i++) {
   elmCenter.innerHTML = elmCenter.innerHTML.replace(/<br>/, '');
  }
 }
}
document.forms.namedItem('f') && accHomePage( );
document.forms.namedItem('gs') && accSearchResults( );
removeFontTags( );
zoomStyle( );

Running the Hack

After installing the user script (Tools Install This User Script), go to http://www.google.com. The normally spartan search form has been magnified and simplified even further, as shown in Figure 8-19.

Accessibility studies have shown that low-vision users have an easier time reading light text on a dark background, so therefore the page is displayed as white-on-navy. Unvisited links are displayed in yellow; visited links are displayed in light green. The hack removes several elements from the page, including the Advanced Search link, plus any advertisements for Google services or other messages that occasionally appear below the search box.

Figure 8-19. Google home page, zoomed

When you execute a search, the search results are displayed differently, as shown in Figures 8-20 and 8-21, with the following notable differences:

Figure 8-20. Google search results, zoomed

Figure 8-21. Bottom of Google search results, zoomed

If you click the Images link at the top of the page to search for the same keywords in Google Image Search, you will see that the image search results have been similarly hacked, as shown in Figure 8-22.

Figure 8-22. Google image results, zoomed

As with the web search results, the top navigation has been simplified, the number of results is more prominent, and the "Goooooooogle" navigation bar has been replaced by a single "More results" link that moves to the next page of images. The image thumbnails themselves cannot be magnified, since Google provides them only in a specific size.