function ColdCode(input, code) {
   this.charCodes = {
      ' ': [['none','none','none','none','none','none','none','none','none','none']],
      'A': [['black','gray','gray','white','none','none','none','none','none','none']],
      'B': [['black','gray','none','none','none','none','yellow','green','green','blue']],
      'C': [['none','none','gray','white','red','orange','orange','yellow','none','none']],
      'D': [['black','gray','none','none','none','none','yellow','green','none','none']],
      'E': [['black','gray','none','none','none','none','none','none','none','none']],
      'F': [['black','gray','none','none','red','orange','orange','yellow','none','none']],
      'G': [['none','none','gray','white','none','none','yellow','green','green','blue']],
      'H': [['none','none','none','none','red','purple','none','none','purple','blue']],
      'I': [['none','none','gray','white','red','orange','none','none','none','none']],
      'J': [['black','gray','gray','white','none','none','yellow','green','none','none']],
      'K': [['black','gray','gray','white','red','orange','orange','yellow','none','none']],
      'L': [['none','none','gray','white','none','none','none','none','green','blue']],
      'M': [['none','none','none','none','red','orange','orange','green','green','blue']],
      'N': [['none','none','none','none','red','orange','orange','yellow','none','none']],
      'O': [['none','none','none','none','none','none','yellow','green','green','blue']],
      'P': [['none','none','gray','white','red','purple','none','none','purple','blue']],
      'Q': [['black','gray','gray','white','red','purple','none','none','purple','blue']],
      'R': [['none','none','gray','white','none','none','yellow','green','none','none']],
      'S': [['black','gray','none','none','red','orange','none','none','none','none']],
      'T': [['none','none','none','none','none','none','none','none','green','blue']],
      'U': [['black','gray','gray','white','red','orange','none','none','none','none']],
      'V': [['none','none','gray','white','red','orange','orange','green','green','blue']],
      'W': [['black','gray','gray','white','none','none','none','none','green','blue']],
      'X': [['black','gray','none','none','red','orange','orange','green','green','blue']],
      'Y': [['black','gray','none','none','red','purple','none','none','purple','blue']],
      'Z': [['black','gray','none','none','none','none','none','none','green','blue']],
      /* the liner notes don't define a symbol for 0, but 10 is defined
         10 is the symbol for 1 with a third column appended
         therefore, I use that third column prefaced with the column begining every other numeral */
      '0': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['none','none','gray','white','red','purple','none','none','purple','blue']],
      '1': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['black','gray','gray','white','red','purple','none','none','purple','blue']],
      '2': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['black','gray','gray','white','none','none','none','none','green','blue']],
      '3': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['black','gray','none','none','none','none','none','none','none','none']],
      '4': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['none','none','gray','white','none','none','yellow','green','none','none']],
      '5': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['none','none','none','none','none','none','none','none','green','blue']],
      '6': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['black','gray','none','none','red','purple','none','none','purple','blue']],
      '7': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['black','gray','gray','white','red','orange','none','none','none','none']],
      '8': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['none','none','gray','white','red','orange','none','none','none','none']],
      '9': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['none','none','gray','white','none','none','yellow','green','green','blue']],
      /* 10 is represented by # */
      '#': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['black','gray','gray','white','red','purple','none','none','purple','blue'],
            ['none','none','gray','white','red','purple','none','none','purple','blue']],
      '(': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['black','gray','gray','white','red','orange','orange','yellow','none','none']],
      ')': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['none','none','gray','white','none','none','none','none','green','blue']],
      ',': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['none','none','none','none','red','orange','orange','yellow','none','none']],
      '.': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['none','none','none','none','red','orange','orange','green','green','blue']],
      '&': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['none','none','none','none','none','none','yellow','green','green','blue']],
      '?': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['black','gray','none','none','none','none','yellow','green','green','blue']],
      '!': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['black','gray','none','none','red','orange','orange','yellow','none','none']],
      '/': [['black','gray','gray','white','none','none','yellow','green','green','blue'],
            ['black','gray','none','none','red','orange','orange','green','green','blue']]
   };
   
   this.code = code;
   this.showing = '';
   
   this.convertString = function(){
      var inputString, numCommonChars, i;
      /* remove unknown characters from input */
      inputString = this.input.value.replace(/[^a-z0-9\s\(\),\.&\?!\/]/ig, '').toUpperCase();
      /* represent 10 with a single character */
      inputString = inputString.replace(/(?:(\D)|^)10(?=(\D)|$)/g, '$1#$2');
      
      numCommonChars = 0;
      while (this.showing.length > numCommonChars && inputString.length > numCommonChars &&
         this.showing.charAt(numCommonChars) === inputString.charAt(numCommonChars)) {
         ++numCommonChars;
      }
      for(i=this.showing.length-numCommonChars; i>0; --i) {
         this.code.removeChild(this.code.lastChild);
      }
      this.showing = this.showing.substring(0, numCommonChars);
      
      while(this.showing.length<inputString.length){
         this.code.appendChild(this.buildChar(inputString.charAt(this.showing.length)));
         this.showing += inputString.charAt(this.showing.length);
      }
   };
   
   this.buildChar = function(letter){
      var characterDiv, cols, col, columnDiv, rows, row, dividerDiv, className, blockDiv;
      characterDiv=document.createElement('div');
      characterDiv.title=(letter === '#')?'10':letter;
      characterDiv.className='character';
      cols=this.charCodes[letter];
      for(col=0;col<cols.length;++col){
         columnDiv=document.createElement('div');
         columnDiv.className='column';
         rows=cols[col];
         for(row=0;row<rows.length;++row){
            if(row===4){
               dividerDiv=document.createElement('div');
               className = 'divider';
               if (cols.length > 1) {
                  if (col===0) { className = 'left '+className; }
                  else if (col<cols.length-1) { className = 'center '+className; }
                  else { className = 'right '+className; }
               }
               if (letter!==' ') { className = 'red '+className; }
               dividerDiv.className = className;
               columnDiv.appendChild(dividerDiv);
            }
            blockDiv=document.createElement('div');
            blockDiv.className=(row%2===0) ? rows[row]+' block' : rows[row]+' bottom block';
            columnDiv.appendChild(blockDiv);
         }
         characterDiv.appendChild(columnDiv);
      }
      return characterDiv;
   };
   
   this.input = input;
   var _this = this;
   input.onchange = function(){_this.convertString();};
   input.onkeyup = input.onchange;
   input.onmouseup = input.onchange;
   input.onfocus = input.onchange;
}

/* for our friends on IE6 */
function ColdCodeNoCSS(input, code) {
   ColdCode.call(this, input, code);
   
   this.blockSize = 30;
   this.colors = {
      'black': '#000000',
      'gray': '#94938E',
      'white': '#FEFFFF',
      'red': '#D32E12',
      'orange': '#EC6E00',
      'yellow': '#F6D017',
      'purple': '#470A58',
      'green': '#007437',
      'blue': '#0033A9',
      'none': 'none'
   };
   
   this.buildChar = function(letter){
      var characterDiv, cols, col, columnDiv, rows, row, dividerDiv, blockDiv;
      characterDiv=document.createElement('div');
      characterDiv.title=(letter === '#')?'10':letter;
      characterDiv.style.cssFloat='left';
      characterDiv.style.styleFloat='left';
      cols=this.charCodes[letter];
      for(col=0;col<cols.length;++col){
         columnDiv=document.createElement('div');
         rows=cols[col];
         for(row=0;row<rows.length;++row){
            if(row===4 && letter!==' '){
               dividerDiv=document.createElement('div');
               dividerDiv.style.position='relative';
               dividerDiv.style.height=this.blockSize/10+'px';
               dividerDiv.style.width=this.blockSize/2+'px';
               dividerDiv.style.left=(col>0)?'0px':this.blockSize/4+'px';
               if(cols.length>1){
                  dividerDiv.style.width= (col===0||col===cols.length-1) ? this.blockSize*3/4+1+'px' : this.blockSize+'px';
               }
               dividerDiv.style.background=this.colors.red;
               dividerDiv.style.margin=this.blockSize/3+'px 0px '+this.blockSize/3+'px 0px';
               columnDiv.appendChild(dividerDiv);
            }
            blockDiv=document.createElement('div');
            blockDiv.style.position='relative';
            blockDiv.style.height=this.blockSize+'px';
            blockDiv.style.width=this.blockSize+'px';
            blockDiv.style.background=this.colors[rows[row]];
            if (row%2===1) {blockDiv.style.margin='0px 0px 10px 0px';}
            columnDiv.appendChild(blockDiv);
         }
         columnDiv.style.cssFloat='left';
         columnDiv.style.styleFloat='left';
         columnDiv.style.width=this.blockSize+'px';
         columnDiv.style.fontSize='0px';
         characterDiv.appendChild(columnDiv);
      }
      return characterDiv;
   };
}

function initColdCode(input, code) {
   var coldCode = (window.XMLHttpRequest) ? new ColdCode(input, code) : new ColdCodeNoCSS(input, code);
   input.focus();
   return coldCode;
}
