2016-10-26 2 views
9

У меня есть форма с полем ввода для дат. Даты должны быть подтверждены: допускаются только даты с сегодняшнего дня + максимум 3 года. Если дата действительна, появится модальная мода, иначе появится сообщение с сообщением об ошибке.onchange + проверка + введите ключевое странное поведение

Предполагая, что Сомон меняет дату на 26.10.2099:

Все работает, как ожидалось, если один выходит из поля ввода (нажав где-нибудь еще с помощью мыши):

  • появляется сообщение об ошибке
  • дата получает автоматически изменяется обратно
  • не модальный показывает

НО если один нажимает Enter вместо того чтобы просто оставить поле ввода, то происходит следующее:

  • сообщения об ошибке не показывает
  • даты получает автоматически изменяется обратно
  • модальные показывает вверх

Моей мысль что изменение даты до ее первоначального значения приводит к тому, что событие onchange будет запущено снова, а затем дата будет действительна и покажет модальность. Но это не относится к первому сценарию. Во втором сценарии событие запускается дважды SOMETIMES, но не всегда.

Вы можете проба себя здесь: https://jsfiddle.net/6x9n53fx/3/

Или прочитать код ниже:

HTML:

<div class="container"> 
    <form method="post" action="" enctype="multipart/form-data"> 
     <div class="row"> 
      <div class="col-sm-6"> 
       <div class="form-group"> 
        <label for="review_date">Valid until *</label> 
        <input id="review_date" type="text" name="review_date" value="26.10.2016" class="form-control"> 
        <p>Please set a validation date. (max 3 years)</p> 
       </div> 
      </div> 
     </div> 
    </form> 
</div> 
<!-- Modal --> 
<div class="modal fade" id="info_modal" tabindex="-1" role="dialog" aria-labelledby="modal_title"> 
    <div class="modal-dialog" role="document"> 
     <div class="modal-content"> 
      <div class="modal-header"> 
       <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> 
       <h4 class="modal-title" id="modal_title">Dialog</h4> 
      </div> 
      <div class="modal-body"> 
       <div class="form-group mbn"> 
        <p class="mb10">Date successfully changed.</p> 
       </div> 
      </div> 
      <div class="modal-footer"> 
       <button type="button" class="btn btn-primary" data-dismiss="modal">Ok</button> 
      </div> 
     </div> 
    </div> 
</div> 

Javascript:

var datumfeld = $("#review_date"); 
var initialdatum = datumfeld.val(); 
var i = 0; 
datumfeld.datepicker({ 
    minDate: 0, 
    maxDate: "3y", 
    dateFormat: 'dd.mm.yy' 
}); 
datumfeld.change(function() { 
i++; 
    console.log('onchange triggered: ' + i); 
    if (validateDatum()) { 
    $("#info_modal").modal({ 
     backdrop: "static", 
     keyboard: false 
    }); 
    } 
}); 

function validateDatum() { 
    var dateParts = datumfeld.val().split("."); 
    var review_date = new Date(dateParts[2], (dateParts[1] - 1), (parseInt(dateParts[0]) + 1)); 
    if (((new Date(review_date - (new Date()))).getFullYear() - 1970) > 2) { 
    alert("Error: The date must not exceed 3 years from now."); 
    datumfeld.val(initialdatum); 
    return false; 
    } 
    if ((review_date - (new Date)) < 0) { 
    alert("Error: The date must not be in the past."); 
    datumfeld.val(initialdatum); 
    return false; 
    } 
    return true; 
} 

EDIT:

Вот окончательное решение, я пошел с:

datumfeld.on('keydown', function(e) { 
    // when keydown is ENTER (13) 
    if (e.keyCode == 13) { 
     // Hide the datepicker 
     $(this).datepicker('hide'); 
     // Trigger a change event to trigger the validation 
     $(this).trigger('change'); 
    } 
    }) 
+0

откуда у ¨R вызова validateDatum()? – user1844933

+0

datumfeld.change() где validateDatum() называется – Danmoreng

+0

Onchange будет срабатывать, когда вы покинете фокус, поэтому вам нужно использовать onkeypress слишком – user1844933

ответ

4

Проблема с вашего кода при нажатии Введите ваше значение! = Когда вы нажимаете еще где. Вы можете увидеть его при отладке dateParts

При вводе примера: 28.10.2099 и щелкнуть по кнопке dateParts является [ "28", "10", "2099"] Но когда введите пример: 28.10.2099 и нажмите ENTER dateParts is ["28", "10", "2019"] Здесь datepicker проверяет поле ввода и автоматически устанавливает дату до 28.10.2019, потому что вы установили maxDate в 3y.

Таким образом, мое решение состоит в том, чтобы связать keydown и обходить datepicker, прежде чем он автоматически изменит значение.

Вот ссылка с рабочим кодом: https://jsfiddle.net/95qbs86x/2/

Update: добавлен код

var datumfeld = $("#review_date"); 
var initialdatum = datumfeld.val(); 
var i = 0; 

// bind keydown event 
datumfeld.on('keydown', function(e) { 
    // when keydown is ENTER (13) 
    if (e.keyCode == 13) { 

    // trigger tab to hide datepicker 
    var e = $.Event("keydown"); 
    e.which = 9; //tab 
    e.keyCode = 9; 
    e.key = 'Tab'; 
    $(this).trigger(e); 

    return false; 
    } 
}).datepicker({ 
    minDate: 0, 
    maxDate: "3y", 
    dateFormat: 'dd.mm.yy', 
    onClose: function(){ 
    this.blur(); 
    } 
}).on('change', function(e) { 
    i++; 
    console.log('onchange triggered: ' + i); 
    if (validateDatum()) { 
    $("#info_modal").modal({ 
     backdrop: "static", 
     keyboard: false 
    }); 
    } 
}); 


function validateDatum() { 
    var dateParts = datumfeld.val().split("."); 
    console.log(dateParts); 
    var review_date = new Date(dateParts[2], (dateParts[1] - 1), (parseInt(dateParts[0]) + 1)); 

    if (((new Date(review_date - (new Date()))).getFullYear() - 1970) > 2) { 
    alert("Error: The date must not exceed 3 years from now."); 
    datumfeld.val(initialdatum); 
    return false; 
    } 
    if ((review_date - (new Date)) < 0) { 
    alert("Error: The date must not be in the past."); 
    datumfeld.val(initialdatum); 
    return false; 
    } 
    return true; 
} 

Примечание: Некоторые код можно удалить так: e.which = 9;e.key = 'Tab';return false;

Однако в применяя тот же эффект, что и щелчок, эта строка кода должна быть добавлена:

onClose: function(){ 
    this.blur(); 
} 

Некоторый код был взят из этого answere: Disable enter key in JQuery ui datepicker

+0

Спасибо за ваш ответ. Это помогло совсем немного, хотя я не занимался созданием события нажатия клавиши, а встроенный метод hide для datepicker. Также я просто запускаю событие изменения вместо дублирования кода проверки. Я редактировал свое окончательное решение в вопросе. – Danmoreng

0

Вы должны использовать preventDefault(), чтобы справиться с этой проблемой, работая демо приведенной ниже ...

  $(document).ready(function() { 
 
       var datumfeld = $("#review_date"); 
 
       var initialdatum = datumfeld.val(); 
 
       var i = 0; 
 
       datumfeld.datepicker({ 
 
        minDate: 0, 
 
        maxDate: "3y", 
 
        dateFormat: 'dd.mm.yy' 
 
       }); 
 
       datumfeld.change(function(e) { 
 
       i++; 
 
        console.log('onchange triggered: ' + i); 
 
        if (validateDatum()) { 
 
        e.preventDefault(); 
 
        $("#info_modal").modal({ 
 
         backdrop: "static", 
 
         keyboard: false 
 
        }); 
 
        } 
 
       }); 
 

 
       function validateDatum() { 
 
        var dateParts = datumfeld.val().split("."); 
 
        var review_date = new Date(dateParts[2], (dateParts[1] - 1), (parseInt(dateParts[0]) + 1)); 
 
        if (((new Date(review_date - (new Date()))).getFullYear() - 1970) > 2) { 
 
        alert("Error: The date must not exceed 3 years from now."); 
 
        datumfeld.val(initialdatum); 
 
        return false; 
 
        } 
 
        else if ((review_date - (new Date)) < 0) { 
 
        alert("Error: The date must not be in the past."); 
 
        datumfeld.val(initialdatum); 
 
        return false; 
 
        } else { 
 
        return true; 
 
        } 
 
       } 
 

 
       function handleSubmit() { 
 
        console.log("form submitted...."); 
 
        return false; 
 
       } 
 
      });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> 
 
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css"> 
 
<script type="text/javascript" src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script> 
 
<link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"> 
 
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> 
 
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css"> 
 
<script type="text/javascript" src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"></script> 
 
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> 
 
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> 
 
<div class="container"> 
 
      <form method="post" action="" enctype="multipart/form-data" onsubmit="return handleSubmit();"> 
 
       <div class="row"> 
 
        <div class="col-sm-6"> 
 
         <div class="form-group"> 
 
          <label for="review_date">Valid until *</label> 
 
          <input id="review_date" type="text" name="review_date" value="26.10.2016" class="form-control"> 
 
          <p>Please set a validation date. (max 3 years)</p> 
 
         </div> 
 
        </div> 
 
       </div> 
 
      </form> 
 
     </div> 
 
     <!-- Modal --> 
 
     <div class="modal fade" id="info_modal" data-controls-modal="info_modal" data-backdrop="static" tabindex="-1" role="dialog" aria-labelledby="modal_title" data-keyboard="false"> 
 
      <div class="modal-dialog" role="document"> 
 
       <div class="modal-content"> 
 
        <div class="modal-header"> 
 
         <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> 
 
         <h4 class="modal-title" id="modal_title">Dialog</h4> 
 
        </div> 
 
        <div class="modal-body"> 
 
         <div class="form-group mbn"> 
 
          <p class="mb10">Date successfully changed.</p> 
 
         </div> 
 
        </div> 
 
        <div class="modal-footer"> 
 
         <button type="button" class="btn btn-primary" data-dismiss="modal">Ok</button> 
 
        </div> 
 
       </div> 
 
      </div> 
 
     </div>

Объяснение:

Вы правы в изменении даты до ее первоначального значения, заставляя событие onchange снова запускаться, в то время вам нужно справиться с этой проблемой, поэтому для ее обработки существует опция preventDefault(), я привел рабочий пример которые вам требуются для этого и для справки, вы можете проверить эти ссылки. Reference_1, Reference_2, Reference_3 ...

+1

Не работает для меня. Нажмите на поле ввода, вручную измените год на 2099, затем нажмите Enter -> модальный. Сделайте то же самое без нажатия Enter, но вместо этого нажмите где-нибудь снаружи -> Появится сообщение об ошибке. (второе поведение - это то, что должно произойти при нажатии клавиши Enter) – Danmoreng

0

Датчик даты запускает событие изменения, как только вы нажимаете «Ввод», и меняет дату, как только дата не подходит к minDate или maxDate самого датпикера.

Поэтому я обновил обработчик событий для событий keyup и уничтожил дату, как только вы набираете что-либо с помощью клавиатуры (=> означает, что вы не хотите вводить дату с помощью datepicker), и я его перезагружаю как только вы нажмете ENTER.

Это окончательный код JavaScript:

var datumfeld = $("#review_date"); 
    var initialdatum = datumfeld.val(); 
    var i = 0; 

    datumfeld.datepicker({ 
     minDate: 0, 
     maxDate: "3y", 
     dateFormat: 'dd.mm.yy' 
    }); 

    datumfeld.on('keyup change', function(e) { 
    e.preventDefault(); 
    if(e.key && e.key === "Enter") { 
     e.stopImmediatePropagation(); 
     datumfeld.datepicker({ 
     minDate: 0, 
     maxDate: "3y", 
     dateFormat: 'dd.mm.yy' 
     }); 
    } else if(e.key) { 
     datumfeld.datepicker("destroy"); 
    } 
    if(!e.key || e.key === "Enter") { 
     i++; 
     console.log('onchange triggered: ' + i); 
     if (validateDatum()) { 
     $("#info_modal").modal({ 
      backdrop: "static", 
      keyboard: false 
     }); 
     } 
    } 
    }); 

    function validateDatum() { 
     var dateParts = datumfeld.val().split("."); 
     var review_date = new Date(dateParts[2], (dateParts[1] - 1), (parseInt(dateParts[0]) + 1)); 
     if (((new Date(review_date - (new Date()))).getFullYear() - 1970) > 2) { 
     alert("Error: The date must not exceed 3 years from now."); 
     datumfeld.val(initialdatum); 
     return false; 
     } 
     if ((review_date - (new Date)) < 0) { 
     alert("Error: The date must not be in the past."); 
     datumfeld.val(initialdatum); 
     return false; 
     } 
     return true; 
    } 

Как-то .datepicker("destroy") не работает на JSFiddle, но это, безусловно, существует: http://api.jqueryui.com/datepicker/#method-destroy

e.stopImmediatePropagation(); помог, а когда только проверка на ENTER KeyUp, однако он работает только каждый второй раз. Иногда keyup быстрее, иногда datepicker. Вот почему я хотел уничтожить дампикера.

0

если событие изменения обжигают динамически вы получите originalEvent свойства в случае, если вы можете использовать

if(typeof e.originalEvent!='undefined') return; 

вместо preventDefault хотя оба пути же скрипка здесь https://jsfiddle.net/6x9n53fx/4/

Смежные вопросы