(function($) {
  $.fn.caret=function(begin,end){  
    if(this.length==0) return;

    if (typeof begin == 'number') {
      end = (typeof end == 'number')?end:begin;  
      return this.each(function(){
        if(this.setSelectionRange){
          this.focus();
          this.setSelectionRange(begin,end);
        }else if (this.createTextRange){
          var range = this.createTextRange();
          range.collapse(true);
          range.moveEnd('character', end);
          range.moveStart('character', begin);
          range.select();
        }
      });
    } else {
      if (this[0].setSelectionRange){
        begin = this[0].selectionStart;
        end = this[0].selectionEnd;
      }else if (document.selection && document.selection.createRange){
        var range = document.selection.createRange();      
        begin = 0 - range.duplicate().moveStart('character', -this[0].value.length);
        end = begin + range.text.length;
      }
      return {begin:begin,end:end};
    }       
  };

  // Figure out what the cursor position would be if there was no punctuation.
  function translateFromMoney(string, currentCaretPosition) {
    return currentCaretPosition - string.substr(0, currentCaretPosition).replace(/\d/g,'').length;
  }
  
  // Figure out the cursor position taking non-digits into account given a translateFromMoney position
  function translateToMoney(string, currentCaretPosition) {
    var regexp = new RegExp("(?:\\D*\\d){"+currentCaretPosition+"}");
    var match = string.match(regexp);
    return Math.max(1, match ? match[0].length : 0);
  }
  
  // Take a string, remove all non-digit characters, and return a currency string with delimiters"
  function formatCurrency(s, currency) {
    var numberString = s.replace(/\D/g,'');
    
    // If the number is non-zero, reformat it. We don't do this for zero
    // so that deleting the 1 out of "100,000" doesn't yield blank.
    if (/[^0]/.test(numberString)) {
      numberString = String(Math.round(numberString));
    }
    
    var offset = (numberString.length % 3) || 3;
    var firstPart = numberString.slice(0, offset);
    var secondPart = numberString.slice(offset, numberString.length);
    return currency + firstPart + secondPart.replace(/(...)/g,",$1");
  }  
  
  $(document).ready(function() {
    $("input.money").each(function() {
      var input = $(this);
      var currency = input.attr("currency") || "$";
      
      // Ensure the content of the input is formatted correctly initially.
      input.val(formatCurrency($(this).val(), currency));
      
      // Reformat the input if the value has changed.
      var oldValue = input.val();
      input.keyup(function() {
        var input = $(this);
        var inputValue = input.val();
        if (inputValue != oldValue) {
          var cursorDigitPosition = translateFromMoney(inputValue, input.caret().begin)
          var newInputValue = formatCurrency(inputValue, currency);
          input.val(newInputValue);
          input.caret(translateToMoney(newInputValue, cursorDigitPosition));
          oldValue = newInputValue;
        }
      });
    });
  });
})(window.jQuery);
