﻿// Register our namespaces
Type.registerNamespace('AjaxTutorial');

// EnhancedTextBox constructor
AjaxTutorial.EnhancedTextBox = function(element) 
{
  // initialize base class
  AjaxTutorial.EnhancedTextBox.initializeBase(this, [element]);  

  // setup the initial state
  this._onKeyUpHandler = null;
  this._onKeyPressHandler = null;
  this._onFocusHandler = null;  
  this._dictionary = null;
  this._index = 0;
  this._prefix = "";  
  this._timer = null;
  this._interval = 2000; 
  this._onTickHandler = null;
  this._wasKeyUpDownPressed = false;
  this._wasAnyKeyPressed = false;
}

// EnhancedTextBox members
AjaxTutorial.EnhancedTextBox.prototype = 
{
  // initialize 
  initialize: function() 
  {
    // initialize base class
    AjaxTutorial.EnhancedTextBox.callBaseMethod(this, 'initialize');        

    // create the dictionary      
    this._dictionary = new AjaxTutorial.Dictionary();
    
    // KeyUp                
    this._onKeyUpHandler = Function.createDelegate(this, this._onKeyUp);
    $addHandler(this.get_element(), 'keyup', this._onKeyUpHandler);
    
    // KeyPress                
    this._onKeyPressHandler = Function.createDelegate(this, this._onKeyPress);
    $addHandler(this.get_element(), 'keypress', this._onKeyPressHandler);
    
    // Focus    
    this._onFocusHandler = Function.createDelegate(this, this._onFocus);
    $addHandler(this.get_element(), 'focus', this._onFocusHandler);
    
    // Tick
    this._onTickHandler = Function.createDelegate (this, this._onTick);      
        
    this._timer = $create(AjaxTutorial.Timer, {interval:this._interval, enabled:true}, {tick:this._onTickHandler}, null, null);
    
    // focus on the DOM element
    this.get_element().focus();    
  },
  
  // dispose
  dispose: function() 
  {   
    // remove the event handlers    
    $removeHandler(this.get_element(), 'keyup', this._onKeyUpHandler);
    $removeHandler(this.get_element(), 'keypress', this._onKeyPressHandler);
    $removeHandler(this.get_element(), 'focus', this._onFocusHandler);
    
    // make sure the timer is not enabled
    if(this._timer) {
      this._timer.remove_tick(this._onTickHandler);                        
    }  
        
    // call dispose of the base calss
    AjaxTutorial.EnhancedTextBox.callBaseMethod(this, 'dispose');    
  },
  
  // interval getter
  get_interval: function() 
  {
    return this._interval;
  },

  // interval setter
  set_interval: function(value) 
  {
    if(value != this._interval) {
      this._interval = value;
      this.raisePropertyChanged('interval');
      if(this._timer)
         this._timer.set_interval(this._interval);         
    }
  },

  // onFocus handler
  _onFocus: function (e) 
  {
    this._index = 0;    
  },
  
  // onTick handler
  _onTick: function() 
  {
    if(this._wasAnyKeyPressed && !this._wasKeyUpDownPressed) {    
      this._index = -1;
      this._prefix = this.get_element().value;
      this._getNextMatchingItem();       
      this._wasAnyKeyPressed = false;
    }
  },

  // onKeyPress handler
  _onKeyPress: function(e) 
  {
    this._wasAnyKeyPressed = true;        
  },

  // onKeyUp handler
  _onKeyUp: function(e) 
  {
    this._wasKeyUpDownPressed = false;
            
    if (e.keyCode == Sys.UI.Key.down) {    
      this._wasKeyUpDownPressed = true;
      this._getNextMatchingItem();
      return;
    } 
   
    if (e.keyCode == Sys.UI.Key.up) {     
       this._wasKeyUpDownPressed = true;
       this._getPreviousMatchingItem();      
       return;
    }            

    // fix for IE where backspace and delete keypress is not raised
    if (e.keyCode == Sys.UI.Key.backspace || 
        e.keyCode == Sys.UI.Key.del)
      this._wasAnyKeyPressed = true;   
  },
  
  // Type ahead
  _selectRange : function(start,length)
  {
    var element = this.get_element();
    // IE
    if (element.createTextRange)
    {
      var range = element.createTextRange();
      range.moveStart("character", start);        
      range.moveEnd("character", length - range.text.length);
      range.select();    
    }
    // FF
    else if (element.setSelectionRange)
    {
      element.setSelectionRange(start, length);
    }

    element.focus();
  }, 
  
  // Select the next matching item in the textbox
  _getNextMatchingItem: function() 
  {
    var results = this._dictionary.getMatchingItems(this._prefix);
      
    if(results.length > 0)
    {   
      if (this._index < results.length - 1) this._index++;
      var matchingItem = results[this._index]; 
            
      this.get_element().value = matchingItem;   
      this._selectRange(this._prefix.length, matchingItem.length);
    }   
  },
  
  // Select the previous matching item in the textbox
  _getPreviousMatchingItem: function() 
  {
    var results = this._dictionary.getMatchingItems(this._prefix);
  
    if(results.length > 0)
    {
      if(this._index > 0) this._index--;
      var matchingItem = results[this._index]; 
           
      this.get_element().value = matchingItem;   
      this._selectRange(this._prefix.length, matchingItem.length);       
    }
  }
}

// register the EnhancedTextBox class
AjaxTutorial.EnhancedTextBox.registerClass(
  'AjaxTutorial.EnhancedTextBox', Sys.UI.Control);