• Home
  • Quick Start
    • Configurator
    • Download YUI 3
  • Documentation
    • User Guides
    • Examples
    • Tutorials
    • API Docs
  • Community
    • Gallery
    • Blog
    • Forums
    • YUI Theater
    • Calendar
  • Contribute
    • YUI on GitHub »
    • File a Ticket
    • View Tickets
    • Dashboard
  • Other Projects
    • YUI 2
    • YUI Compressor
    • YUI Doc »
    • YUI Builder
    • YUI PHP Loader
    • YUI Test
    • YUI Website

Blog: Archive for September, 2008

Reading Blinds — a YUI-powered Reading Tool

Ever since I got upgraded to a shiny Macbook Pro and a 24 inch monitor at work I had a web experience that differed a lot from what I had before. Web sites that were easy and nice to read out of a sudden showed a massive amount of white space that actually hurt my eyes. Talking to several people with visual impairments and dyslexia at Scripting Enabled confirmed me that this can be a real issue.

This is why I thought of writing a small script that can be used as a bookmarklet to cover the screen with a dark overlay and only shows a few lines at a time. That way you can concentrate on the bit you are reading at the moment and the rest of the screen does not bother you too much.

Following are two screenshots of the same site with and without reading blinds:

Browser with Reading Blinds

Browser without Reading Blinds

So how to build that?

The task of building a tool like that is actually pretty easy:

  • create two DIVs with black background and 85% opacity
  • position them fixed to the top and the bottom of the screen
  • set their height to 10% and 70% to leave a gap

Then I thought that I should be able to move the highlight on the page. For this I needed a bit more sophistication:

  • Detect the mouse cursor position
  • Make the top div span from the current top of the document to a few pixels above the cursor position
  • Make the bottom div span from a few pixels below the current cursor position to the bottom of the viewport

I could have had a go at it myself, but I don’t want to end in browser inconsistency hell, hence I use YUI.

Here’s the code:

var readingblinds = function(){
  var visible = true;
  var y,top,bottom;
  var info = true;
  var size = 70;
  function generate(){
    top = document.createElement('div');
    bottom = document.createElement('div');
    document.body.appendChild(top);
    document.body.appendChild(bottom);
    styleTopBottom();
    var message = document.createElement('div');
    var note = document.createTextNode(
      'Reading Blinds - ' + 
      'move mouse to highlight section to read. ' 
    );
    message.appendChild(note);
    top.appendChild(message);
    styleMessage(message);
    YAHOO.util.Event.on(document, "mousemove", move);
  };
  function move(e){
    y = YAHOO.util.Event.getXY(e);
    if(y[1] > size){
      render(y);
    }
  };
  function render(y){
    var real = y[1]-YAHOO.util.Dom.getDocumentScrollTop();
    YAHOO.util.Dom.setStyle(top,'height',real-size+'px');
    var h = YAHOO.util.Dom.getViewportHeight()-real+size;    
    YAHOO.util.Dom.setStyle(bottom,'top',real+size+'px');
    YAHOO.util.Dom.setStyle(bottom,'height',h + 'px');
  };
  function styleMessage(message){
    YAHOO.util.Dom.setStyle(message,'font-size','80%');
    YAHOO.util.Dom.setStyle(message,'text-align','right');
    YAHOO.util.Dom.setStyle(message,'padding','5px');
    YAHOO.util.Dom.setStyle(message,'font-family','verdana,sans-serif');
    YAHOO.util.Dom.setStyle(message,'color','white');
  }
  function styleTopBottom(){
    YAHOO.util.Dom.batch([top,bottom],function(o){
      YAHOO.util.Dom.setStyle(o,'background','#000');
      YAHOO.util.Dom.setStyle(o,'width','100%');
      YAHOO.util.Dom.setStyle(o,'position','fixed');
      YAHOO.util.Dom.setStyle(o,'left','0');
      YAHOO.util.Dom.setStyle(o,'height','10%');
      YAHOO.util.Dom.setStyle(o,'opacity','.85');
      YAHOO.util.Dom.setStyle(o,'overflow','hidden');
    });
    YAHOO.util.Dom.setStyle(top,'top','0');
    YAHOO.util.Dom.setStyle(bottom,'bottom',0);
    YAHOO.util.Dom.setStyle(bottom,'height','70%');
  };
  return{
    init:generate
  }
}();
readingblinds.init();

The interesting methods are move() and render(); the rest is more or less run-of-the-mill DOM scripting.

The move() method is an event handler that gets called by any mousemove event on the document. YUI’s Dom Collection then makes it easy for me to get the current mouse cursor position with getXY() and I just need to make sure that the mouse is low enough in the browser window to not cause a negative height on the top div.

The render() method then sets the appropriate heights. I determine the upper border of the browser with getDocumentScrollTop() and substract that one from the cursor position. To determine where to end the bottom div I use getViewPortHeight().

Addding dazzle with keyboard controls

This was cool enough, but I wanted to be able to turn the blinds on and off and change the size of the visible part with the keyboard, too. For this, I needed to use the keylistener utility some tool methods to resize the gap or show and hide both of the cover divs. The resizing methods needed to get some boundaries to avoid div overlap or the whole viewport to be uncovered.

var readingblinds = function(){
  var visible = true;
  var y,top,bottom;
  var info = true;
  var size = 70;
  function generate(){
    top = document.createElement('div');
    bottom = document.createElement('div');
    document.body.appendChild(top);
    document.body.appendChild(bottom);
    styleTopBottom();
    var message = document.createElement('div');
    var note = document.createTextNode(
      'Reading Blinds - ' + 
      'move mouse to highlight section to read. ' +
      'Press "b" to show and hide, "s" to decrease size,' + 
      ' "l" to increase size'
    );
    message.appendChild(note);
    top.appendChild(message);
    styleMessage(message);
    var keyspy = new YAHOO.util.KeyListener(
      document, 
      { keys:66 }, 
      { fn:peekaboo }
    );
    keyspy.enable();
    var keyspy2 = new YAHOO.util.KeyListener(
      document, 
      { keys:83 }, 
      { fn:smaller }
    );
    keyspy2.enable();
    var keyspy3 = new YAHOO.util.KeyListener(
      document, 
      { keys:76 }, 
      { fn:larger }
    );
    keyspy3.enable();
    YAHOO.util.Event.on(document, "mousemove", move);
  };
  function move(e){
    y = YAHOO.util.Event.getXY(e);
    if(y[1] > size){
      render(y);
    }
  };
  function render(y){
    var real = y[1]-YAHOO.util.Dom.getDocumentScrollTop();
    YAHOO.util.Dom.setStyle(top,'height',real-size+'px');
    YAHOO.util.Dom.setStyle(bottom,'top',real+size+'px');
    var h = YAHOO.util.Dom.getViewportHeight()-real+size;    
    YAHOO.util.Dom.setStyle(bottom,'height',h + 'px');
  };
  function styleMessage(message){
    YAHOO.util.Dom.setStyle(message,'font-size','80%');
    YAHOO.util.Dom.setStyle(message,'text-align','right');
    YAHOO.util.Dom.setStyle(message,'padding','5px');
    YAHOO.util.Dom.setStyle(message,'font-family','verdana,sans-serif');
    YAHOO.util.Dom.setStyle(message,'color','white');
  }
  function styleTopBottom(){
    YAHOO.util.Dom.batch([top,bottom],function(o){
      YAHOO.util.Dom.setStyle(o,'background','#000');
      YAHOO.util.Dom.setStyle(o,'width','100%');
      YAHOO.util.Dom.setStyle(o,'position','fixed');
      YAHOO.util.Dom.setStyle(o,'left','0');
      YAHOO.util.Dom.setStyle(o,'height','10%');
      YAHOO.util.Dom.setStyle(o,'opacity','.85');
      YAHOO.util.Dom.setStyle(o,'overflow','hidden');
    });
    YAHOO.util.Dom.setStyle(top,'top','0');
    YAHOO.util.Dom.setStyle(bottom,'bottom',0);
    YAHOO.util.Dom.setStyle(bottom,'height','70%');
  };
  function peekaboo(){
    if(visible === true){
      YAHOO.util.Dom.setStyle(top,'display','none');
      YAHOO.util.Dom.setStyle(bottom,'display','none');
      visible = false;
    } else {
      YAHOO.util.Dom.setStyle(top,'display','block');
      YAHOO.util.Dom.setStyle(bottom,'display','block');
      visible = true;
    }
  };
  function smaller(){
    if(size > 10){
      size -= 5;
      render(y);
    }
  };
  function larger(){
    if(size <  YAHOO.util.Dom.getViewportHeight()/2){
      size += 5;
      render(y);
    }
  };
  return{
    init:generate
  }
}();
readingblinds.init();

That was pretty cool already, but as I wanted to make reading blinds a single script include or bookmarklet I had the problem of relying on the YUI. Well, there is a trick to conjure YUI from thin air by using the YAHOO_config object with the listener method creating a script node to get the YUI Loader.

So instead of calling readingblinds.init() directly, I used the following magic YUI trick:

if(typeof YAHOO=="undefined"||!YAHOO){
  YAHOO_config = function(){
    var s = document.createElement('script');
    s.setAttribute('type','text/javascript');
    s.setAttribute('src','http://yui.yahooapis.com/2.5.2/'+
                   'build/yuiloader/yuiloader-beta-min.js');
    document.getElementsByTagName('head')[0].appendChild(s);
    return{
      listener:function(o){
        if(o.name === 'get'){
          window.setTimeout(YAHOO_config.ready,1);
        }
      },
      ready:function(){
        var loader = new YAHOO.util.YUILoader();
        var dependencies = ['yahoo','dom','event'];
        loader.require(dependencies);
        loader.loadOptional = true;
        loader.insert({
          onSuccess:function(){
            readingblinds.init();
          }
        });
      }
    };
  }();
} else {
  readingblinds.init();
}

That’s the lot. You can download readingblinds.js
and include it in your site, or you can drag the following link to your links toolbar: Reading Blinds.

By Christian HeilmannSeptember 30th, 2008

Free Chapter: “Coding and Design Patterns” from Stoyan Stefanov’s Object-Oriented JavaScript

Stoyan Stefanov's 'Object Oriented JavaScript' [book cover]Stoyan Stefanov is a member of Yahoo’s Exceptional Performance team; he’s worked on a variety of performance-related projects at Yahoo, including the popular YSlow plugin for Firebug. He’s also a contributing author here on YUIBlog.

Stoyan’s latest project is Object Oriented JavaScript, a new book from Packt whose simple goal is to help you learn how to “think in JavaScript.” Stoyan and his editors were kind enough to let us share with you Chapter 8 from OOJS — “Coding and Design Patterns.”

  • Chapter 8 from Object Oriented JavaScript by Stoyan Stefanov: “Coding and Design Patterns” (1.8MB PDF)

Among the coding patterns explored in this chapter:

  • Separating behavior
  • Namespaces
  • Init-time branching
  • Lazy definition
  • Configuration objects
  • Private variables and methods
  • Privileged methods
  • Private functions as public methods
  • Self-executable functions
  • Chaining
  • JSON

Design patterns include:

  • Singleton
  • Factory
  • Decorator
  • Observer

The sample chapter is an excellent standalone resource, but the full volume is outstanding as well. Our thanks to Stoyan and his editors for allowing us to freely share the coding and design patterns content here.

By Eric MiragliaSeptember 26th, 2008

Reminder: YUI 3.x Meetup Tonight and Yahoo! Live Channel Info

If you can’t make it to the YUI meetup tonight but you do want to drop in and see what’s going on, we’ll be broadcasting the event on the experimental Yahoo! Live service:

  • http://live.yahoo.com/miraglia

Live is a relatively recent product out of Yahoo’s Brickhouse development incubator. We haven’t used it for this purpose before, but since we’ll be up at Brickhouse for tomorrow night’s meetup we thought we’d highlight some of that group’s fantastic work.

Hope to see you online or in person tonight!

Note: The Live channel will not be broadcasting all day — just from about 7:15 p.m. through the end of the code demos. Drop in after 7:15 p.m. PDT tonight and, barring any technical challenges, you should find us there.

By Eric MiragliaSeptember 3rd, 2008

Another YUI-based Game from Kris Cieslak: Pacman

Visit Kris's new game at digitalinsane.com.Kris Cieslak is back, after a long break, with a new YUI-based game: Pacman. We last heard from Kris about 18 months ago, when he was showing off Yetris, Puzzle and Solitaire. Now Kris returns with another classic game built entirely in JavaScript, bolstered by YUI 2.5.2′s core (Yahoo, Dom and Event). Check it out and give Kris feedback on his blog.

By Eric MiragliaSeptember 2nd, 2008

Pages

  • About
  • Contribute
  • YUI Jobs

Recent Posts

  • YUI Weekly for May 17th, 2013
  • Yahoo’s International Team Is Hiring!
  • YUICompressor 2.4.8 Released
  • YUI 3.10.1 Released to Fix SWF Vulnerability
  • YUI Weekly for May 10th, 2013

Archives

Categories

  • Accessibility (25)
  • CSS 101 (6)
  • Design (51)
  • Development (590)
  • Frontend Jobs at Yahoo (13)
  • Graded Browser Support (8)
  • In the Wild (63)
  • Miscellany (11)
  • Open Hours (44)
  • Performance (23)
  • Releases (25)
  • Target Environments (11)
  • Yeti (3)
  • YUI 3 Gallery (29)
  • YUI Events (45)
  • YUI Implementations (55)
  • YUI Theater (146)
  • YUI Weekly (37)

Meta

  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
© 2013 YUI Blog