Search code examples
jqueryruby-on-railsinputcoffeescriptruby-on-rails-5

How do I restrict typing data into a date field to only certain charaters?


I'm creating a Rails 5 app. I have a coffee script file in which I'd like to create a function that restricts someone entering a date object by typing in data. I would like the form to be like

12/31/2017

but i would like the person to only be able to enter numbers (and move the cursor around with the arrow keys). I would like the slashes to be automatically added. I tried creating this

add_slahes_to_date = (input) ->
  if input.value != input.value.replace(/[^0-9\.]/g, '')
    input.value = input.value.replace(/[^0-9\.]/g, '')
  v = input.value
  if v.match(/^\d{2}$/)
    input.value = v + '/'
  else if v.match(/^\d{2}\/\d{2}$/)
    input.value = v + '/'

but it has several problems. It will automatically add a slash, but on the next entry it will remove the slash. Also when the slash is added, I'm not able to hit the left arrow to go back and edit the numbers before the first slash.

What's the right way to restrict date entry to just numbers but have the slashes auto-added? I'm using jQuery too if taht helps.


Solution

  • There is two things here...

    1. Restrict the field character to numbers
    2. The slashes auto add

    And I would add a date validation... Since 55/66/9999 is obviously not a valid date.

    So to validate a date, I suggest the use of Moment.js.

    I also added a year limitation (between 1980 and 2050 in the example).

    Then... The user has to be able to correct a mistake, so the backspace key, delete key and left/right arrows are allowed.

    $('.date')
      .on("keydown",function(e){
      //console.log(e.which);
      
      // Remove error background-color
      $(this).css({"background-color":"initial"});
    
      // Diallow character that are not a numbers 0 to 9 (both keypads), but allow backspace and left/right arrows
      if( (e.which<48 || e.which>57) && (e.which<96 || e.which>105) && e.which!=8 && e.which!=46 && e.which!=37 && e.which!=39){
        return false;
      }
      
    }).on("keyup",function(e){
      if(e.which!=8 && e.which!=46 && e.which!=37 && e.which!=39){
        var value = $(this).val();
    
        // Auto add slashes
        pattern = /(\d{1,2})?(\/)?(\d{1,2})/g;
        var match = value.match(pattern);
        //console.log(match);
    
        if( (value.length==2 || value.length==5) && typeof(match)!="null" ){
          $(this).val(match+"/");
        }
    
        // When all digits are entered
        if( value.length==10 ){
    
    
          var date = value.split("/");
          var valid;
          if( (parseInt(date[2])>=1980) && (parseInt(date[2])<=2050) ){
    
            // Use Moment to validate the date. Will return "invalid date" on impossible dates
            valid = moment(date[2]+"-"+date[0]+"-"+date[1]).format("MM/DD/Y");
    
          }else{
            valid = "Invalid date";
          }
    
          // Show error color to user
          if(valid=="Invalid date"){
            $(this).css({"background-color":"red"});
          }else{
            $(this).css({"background-color":"green"}).trigger("blur");
          }
        }
      }
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>
    
    <input class="date" placeholder="MM-DD-YYYY"></input>