Monday, April 30, 2012

How to code position fixed content on a browser.

While representing sequence text alignment on a browser, it is very useful to have a static genome reference on the top of the page, that descends as you scroll down. So, you are actually not loosing track of the reference but at the same time you see the read alignments and their position with respect to the genome. The genome references can be long and the browser width is not enough to contain it in a single view. So, there will be a lot of room for horizontal scrolling. In this case you want the reference on the top behave normally as with any horizontal scroll, but vertically it should be position fixed. Here is an example of what I am talking about:


 I have created this application after realizing its importance in dealing with nextgen sequence alignment viewer. Here are the few fixed libraries, you may find incredibly useful, so better install/download these in your local server.

A large part of the application have been downloaded from mootools site. The following are the files I have downloaded from mootools site:
  • mootools-yui-compressed.js 
From http://code.google.com/p/joomla-scripts-optimized/downloads/detail?name=mootools-yui-compressed.js&can=2&q=

  • DemosMain.php from mootools web site:  (If you don't find it in the web site, the source is copy pasted below)
  • Style.php from mootools site (Source code is copy pasted below)
Then bundle up these 3 scripts into a directory say  textStyle.

Now create a Php file and write functions that will print your object of interest Some like this:



 open FH, $fileName or die "Can't open file for reading $! \n";  
 my $count=0;  
 my $start;  
 &printHTMLcode;  
 print "<body>";  
 print "<pre>";  
 while(<FH>){  
     if(/(\d+)\t(\d+)\t(\S+)/){  
         if($count == 0){  
             if($genomeStart >= $2){  
             print "<div id=\"DemoItem2\">";  
                 for(my $i=0; $i<=$genomeStart - $2; $i++){  
                     print "&nbsp;";  
                 }  
             &colorCode($genomeSeq);  
             print "</div><br><br>";  
             $start = $2;  
             }  
             else{  
             print "<div id=\"DemoItem2\">";  
             &colorCode($genomeSeq);  
             $start = $genomeStart+1;  
             print "</div><br><br>";  
             }  
         }  
         for(my $i=0; $i<=($2-$start);$i++){  
             print "&nbsp;";  
         }  
     &colorCode($3);  
     }  
 print "\n";  
 $count++;  
 }  
 print "<script src=\"http://www.eumicrobedb.org/develop/textStyle/mootools-yui-c  
 ompressed.js\" type=\"text/javascript\">   \  
     </script>                  \  
     <script src=\"http://www.eumicrobedb.org/develop/textStyle/demosMain.php  
 \" type=\"text/javascript\">                     \  
     </script>                  \  
 ";  
 print "</pre>";  
 print "</body>";  
 close(FH);  
 }  
 sub printHTMLcode  
 {  
 print "<html>";  
 print "<head>";  
 print "<link rel=\"stylesheet\" href=\"http://www.eumicrobedb.org/develop/textSt  
 yle/style.php\" type=\"text/css\" media=\"screen\">";  
 print "<style type=\"text/css\">  
     #DemoItem2{  
         position: fixed;  
         top   : 10px;  
         left  : 6px;  
         width  : 200px;  
         height : 50px;  
     }  
     #DemoItem2{  
         top: 10px;  
     }  
     </style>";  
 print " <script text=\"text/javascript\">  
         function loadDemo(){  
          var demoTwo = new ScrollSpy({  
                  min: 0,  
                  mode: 'horizontal',  
                  onEnter: function(position,enters) {  
                  },  
                  onLeave: function(position,leaves) {  
                  },  
                  onTick: function(position,state,enters,leaves)  
 {  
                 \$(\"DemoItem2\").style.left = -position.x+ 6+\"  
 px\";  
                  },  
                  container: window  
                 });  
         }  
     </script>  
     </head>  
     <body>  
 \n";  
 }  
I will explain now what all these means.

The file it opens in the while loop is a data file that has sequence and their starting point info. So ignore that part.

There is a function call to printHTML code (marked in red). This function is a style sheet text wrapped. You don't have to wrap it in a function, you could just write it on the top if you like. But it looks messy. Please note that inside printHTML code, I have defined demoItem2 div class that actually does the text/content to scroll down. The main text that scrolls down is within &colorcode function, that actually colors and prints the genome reference that is suppose to be static on the screen.

In the end I am calling the moo tools js files(marked in yellow) that actually lets the content scroll horizontally.

here are the source code for style.php and demomain.php, if you did not find it from the mootools:

Source for style.php
 <?php  
 print "<br>  
 *{<br>  
     margin: 0px;<br>  
     padding: 0px;<br>  
 }<br>  
 <br>  
     body, html{<br>  
         width: 100%;<br>  
         height: 100%;<br>  
 <br>  
     }<br>  
 <br>  
 body{<br>  
     font-family:Gill Sans,sans-serif;<br>  
     background: #2a2a2a;  <br>  
 }<br>  
 <br>  
 #wrap{<br>  
     width: 100%;<br>  
     height: 100%;<br>  
     min-width: 1000px;<br>  
 }<br>  
 <br>  
 #head{<br>  
 height:156px;<br>  
 position:fixed;<br>  
 width:100%;<br>  
 top: 0px;<br>  
 }<br>  
 <br>  
 #main{<br>  
     padding-top:148px;<br>  
 }<br>  
 <br>  
 #logo{<br>  
     background-image:url(images/logo.png);<br>  
     background-position:0 0;<br>  
     height:108px;<br>  
     left:50px;<br>  
     position:absolute;<br>  
     top:26px;<br>  
     width:90px;<br>  
 }<br>  
 <br>  
 #return{<br>  
     color:#FAC500;<br>  
     font-size:13px;<br>  
     position:absolute;<br>  
     right:50px;<br>  
     text-decoration:none;<br>  
     top:122px;<br>  
 } <br>  
 #return:hover{<br>  
     color: #fff;<br>  
 }<br>  
 <br>  
 img, a{<br>  
     outline: none;<br>  
 }<br>  
 <br>  
 h1{<br>  
     color:#FFFFFF;<br>  
     font-family:Helvetica,\"Helvetica Neue\",Arial,sans-serif;<br>  
     font-size:18px;<br>  
     font-weight:normal;<br>  
     letter-spacing:-1px;<br>  
     position:absolute;<br>  
     right:50px;<br>  
     text-shadow:2px 2px 0 #111111;<br>  
     top:95px;<br>  
 }<br>  
 <br>  
 .hr{<br>  
     border-top:1px dashed #555555;<br>  
     height:1px;<br>  
     position:absolute;<br>  
     top:153px;<br>  
     width:100%;<br>  
 }<br>  
 <br>  
 <br>  
 .TabHolder{<br>  
     height: 26px;<br>  
     width: auto;<br>  
     position: fixed;<br>  
     z-index: 100000;<br>  
 }<br>  
 <br>  
 .leftTab, .rightTab{<br>  
     display: inline-block;<br>  
     width: 17px;<br>  
     background-image: url(\"images/leftTabDarker.png\");<br>  
     height: 26px;<br>  
     margin: 0px;<br>  
     float: left;<br>  
 }<br>  
 <br>  
 .rightTab{<br>  
         background-image: url(\"images/rightTabDarker.png\");<br>  
 }<br>  
 <br>  
 .midTab{<br>  
     display: inline-block;<br>  
     width: 17px;<br>  
     background-image: url(\"images/midTabDarker.png\");<br>  
     height: 26px;<br>  
     margin: 0px;<br>  
     min-width: 200px;<br>  
     width: auto;<br>  
     float: left;<br>  
     font-size: 11px;<br>  
     font-family: 'Lucida Sans Unicode', 'Lucida Grande', sans-serif;<br>  
     line-height: 23px;<br>  
     text-shadow: 1px 1px 0px #fff;<br>  
     padding: 0px 2px;<br>  
 }<br>  
 <br>  
 .midTab .midTabcol{<br>  
     text-decoration: none;<br>  
     color: #444;<br>  
     border-right: 1px solid #999;<br>  
     border-left: 1px solid #fff;<br>  
     padding: 0px 10px;<br>  
     display: inline-block;<br>  
     line-height: 12px;<br>  
 }<br>  
 <br>  
 .midTab .midTabcol:first-child{<br>  
     border-left: 0px;<br>  
 }<br>  
 <br>  
 .midTab .midTabcol:last-child, .midTab .lastmidTabcol{<br>  
     border-right: 0px;<br>  
 }<br>  
 <br>  
 .midTab a:hover{<br>  
      color: #111;<br>  
 }<br>  
 <br>  
 .midTab a:focus{<br>  
      position: relative;<br>  
      top: 1px;<br>  
 }<br>  
 <br>  
 .goodBrowsers{<br>  
         display:inline-block;<br>  
         position: relative;<br>  
         top: 3px;<br>  
 }<br>  
 <br>  
 #footerTab{<br>  
     bottom: 0px;<br>  
     right: 100px;<br>  
     bottom: -27px;<br>  
 }<br>  
 <br>  
 <br>  
 ";  
 ?> 
 
Source code for DemosMain.php
 var Page = {  
     initialize: function() {  
          // nice one David Walsh  
          var ss = new ScrollSpy({  
                  min: 0,  
                  mode: 'vertical',  
                  onEnter: function(position,enters) {  
                  },  
                  onLeave: function(position,leaves) {  
                  },  
                  onTick: function(position,state,enters,leaves)  
 {  
                     $("head").style.top = -position.y+"px";  
                  },  
                  container: window  
                 });  
                 if($("footerTab")){  
                     $("footerTab").set('morph', {  
                     duration: 500,  
                     transition: 'Sine:out'  
                 });  
                     setTimeout(function(){  
                             $("footerTab").morph({  
                     'bottom': ['-27px','0px']  
                     });  
                     },750);  
                 }  
                 loadDemo();  
     }  
  }  
  window.addEvent("domready", Page.initialize);  
 var ScrollSpy = new Class({  
     /* implements */  
     Implements: [Options,Events],  
     /* options */  
     options: {  
         min: 0,  
         mode: 'vertical',  
         max: 0,  
         container: window,  
         onEnter: $empty,  
         onLeave: $empty,  
         onTick: $empty  
     },  
     /* initialization */  
     initialize: function(options) {  
         /* set options */  
         this.setOptions(options);  
         this.container = $(this.options.container);  
         this.enters = this.leaves = 0;  
         this.max = this.options.max;  
         /* fix max */  
         if(this.max == 0)  
         {  
             var ss = this.container.getScrollSize();  
             this.max = this.options.mode == 'vertical' ? ss.y : ss.x  
 ;  
         }  
         /* make it happen */  
         this.addListener();  
     },  
     /* a method that does whatever you want */  
     addListener: function() {  
         /* state trackers */  
         this.inside = false;  
         this.container.addEvent('scroll',function() {  
             /* if it has reached the level */  
             var position = this.container.getScroll();  
             var xy = this.options.mode == 'vertical' ? position.y :  
 position.x;  
             /* if we reach the minimum and are still below the max..  
 . */  
             if(xy >= this.options.min && xy <= this.max) {  
                     /* trigger Enter event if necessary */  
                     if(!this.inside) {  
                         /* record as inside */  
                         this.inside = true;  
                         this.enters++;  
                         /* fire enter event */  
                         this.fireEvent('enter',[position  
 ,this.enters]);  
                     }  
                     /* trigger the "tick", always */  
                     this.fireEvent('tick',[position,this.ins  
 ide,this.enters,this.leaves]);  
             }  
             else {  
                 /* trigger leave */  
                 if(this.inside)  
                 {  
                     this.inside = false;  
                     this.leaves++;  
                     this.fireEvent('leave',[position,this.le  
 aves]);  
                 }  
             }  
         }.bind(this));  
     }  
 });  

No comments: