(function() {
    $.fn.tableNav = function(callerSettings) {

        ////////////////////////////////////////////////////////////////////////
        // Normalizing parameters and defining local vars

        var settings = $.extend({

			inputClass: '',
			highlightColor: '',
			defaultColor: ''

        }, callerSettings||{});

        var me = this;
        var prevCell = false;
        
        var editingVal = '';



        ////////////////////////////////////////////////////////////////////////
        // local functions

        function getRow(el) {
        	return $(el).parents('tr').get(0);
        }

        function getCell(el) {
        	return $(el).parents('td').get(0);
        }

        function cellIndex(cell) {
            var ret = false;
            var row = getRow(cell);
            var finded = false;

            if(!$(row).length) { return false; }
        	$(row).find('td').each(function(i) {
        		if(finded) { return true; }
        		if(this == cell) {
        			ret = i;
        			finded = true;
        			return true;
        		}
        	});
        	return ret;
        }

        function goUp(input) {
        	var cell = getCell(input);
        	var ind = cellIndex(cell);
        	if(ind === false) { return false; }
        	var prevRow = $(getRow(input)).prev();
        	while(prevRow.length) {
        		var top = prevRow.find('td').eq(ind);
        		if(top.length) {
					var upInp = top.find('input'+(settings.inputClass.length ? '.'+settings.inputClass : ''));
					if(upInp.length) {
						if(editingVal != $(input).val()) { $(input).change().blur(); }
						upInp.focus();
						break;
					}
        		}
				prevRow = prevRow.prev();
        	}
        }

        function goDown(input) {
        	var cell = getCell(input);
        	var ind = cellIndex(cell);
        	if(ind === false) { return false; }
        	var nextRow = $(getRow(input)).next();

        	while(nextRow.length) {
        		var down = nextRow.find('td').eq(ind);
        		if(down.length) {
					var downInp = down.find('input'+(settings.inputClass.length ? '.'+settings.inputClass : ''));
					if(downInp.length) {
						if(editingVal != $(input).val()) { $(input).change().blur(); }
						downInp.focus();
						break;
					}					
        		}
				nextRow = nextRow.next();
        	}
        }

        function goLeft(input) {
        	var cell     = getCell(input);
        	var prevCell = $(cell).prev();

        	while(prevCell.length) {			
				leftInp = prevCell.find('input'+(settings.inputClass.length ? '.'+settings.inputClass : ''));
				if(leftInp.length) {
					if(editingVal != $(input).val()) { $(input).change().blur(); }
					leftInp.focus();
					break;
				}				
				prevCell = prevCell.prev();
        	}					
        }


        function goRight(input) {
        	var cell     = getCell(input);
        	var nextCell = $(cell).next();
        	while(nextCell.length) {						
				var rightInp = nextCell.find('input'+(settings.inputClass.length ? '.'+settings.inputClass : ''));				
				if(rightInp.length) {				
					if(editingVal != $(input).val()) { $(input).change().blur(); }
					rightInp.focus();
					break;
				}				
				nextCell = nextCell.next();
        	}
        }


        ////////////////////////////////////////////////////////////////////////
        // Keypress handler

        me.find('input'+(settings.inputClass.length ? '.'+settings.inputClass : '')).keydown(function(e) {
        	var funcKey = false;

			// right
            if(e.keyCode == 39) {
                goRight(this);
            	funcKey = true;
            }

			// left
            if(e.keyCode == 37) {
                goLeft(this);
            	funcKey = true;
            }

			// up
            if(e.keyCode == 38) {
                goUp(this);
				funcKey = true;
            }

			// down
            if(e.keyCode == 40) {
                goDown(this);
				funcKey = true;
            }

            return !funcKey;
        });


        // Focus handler

        me.find('input'+(settings.inputClass.length ? '.'+settings.inputClass : '')).focus(function() {
        	if(settings.highlightColor) {
        		var cell = getCell(this);
        		$(prevCell).css('background-color', settings.defaultColor);
        		$(cell).css('background-color', settings.highlightColor);
        		prevCell = cell;
        	}
        	editingVal = $(this).val();
        });



        ////////////////////////////////////////////////////////////////////////

        return this;
    }
})(jQuery);


