Использование jQuery Datepicker с различными форматами даты, но всегда получение/установка в формате ISO8601 с использованием val()

Я пытаюсь написать плагин jQuery для отображения и ввода дат, используя средство выбора даты пользовательского интерфейса jQuery в качестве отправной точки.

Вызов должен выглядеть так:

jQuery(document).ready(function() {

  jQuery(document).find('input.mydatepicker').mydatepicker({
    myformat : 'mm/dd/yy'
  });

});

так что любой ввод, имеющий class="mydatepicker" будет иметь поведение mydatepicker.

Загвоздка в том, что я хотел бы, чтобы myformat поддерживал множество различных форматов даты, однако всякий раз, когда я использую функцию val() для получения/установки даты, я хочу, чтобы она была в формате iso8601 yyyy-mm-dd.

Итак, хотя я указал формат mm/dd/yy выше для инициализации всех элементов, я хочу:

<input type="text" class="mydatepicker" id="myelement" value="02/23/2019">

var mydate = $('#myelement').val();   //mydate = '2019-02-23'

и

$('#myelement').val('2019-02-24');

<input type="text" class="mydatepicker" id="myelement" value="02/24/2019">

Используя методы, описанные здесь: Переопределить функцию jQuery .val()? это то, что я пробовал :

(function($) {

  // options & defaults
  var defaultOptions = {
    myformat : 'mm/dd/yy'
  };

  // attach jQuery.UI datepicker with specified options
  $.fn.mydatepicker = function(options) {
    options = $.extend({}, defaultOptions, options || {});

    return this.each( function() {
      var jq = $(this);
      jq.addClass('plugin-mydatepicker').datepicker({
        dateFormat: options.myformat,
        prevText: '<i class="fa fa-angle-left"></i>',
        nextText: '<i class="fa fa-angle-right"></i>',
        constrainInput: true,
        onSelect: function(date) { 
        }
      });
    });

  }


  // override val() to get/set in ISO8601 regardless of format
  var _origVal = $.fn.val;

  $.fn.val = function(value) {
    if ( $(this).hasClass('plugin-mydatepicker') ) {
      if (arguments.length >= 1) {
        // setter
        return $(this).val('x' + value);
      } 
      else {
        // getter
        return 'x' + $(this).val();
      }
    }
    return _origVal.apply(this, arguments);
  };

})(jQuery);

Здесь происходит несколько вещей:

  • Я получаю ошибку «глубокой рекурсии» всякий раз, когда я вызываю val(), и я действительно не понимаю, почему. У меня нет опыта написания плагинов jQuery.
  • Я еще не выполнил преобразование myformat‹->iso8601, поэтому открыт для предложений о том, как это сделать легко. Практически говоря, myformat может быть ограничен мм/дд/гг и дд/мм/гг, не нужно сходить с ума.
  • Чтобы пометить каждый элемент, к которому прикреплен плагин, я добавляю класс plugin-mydatepicker. Не уверен, что это лучший способ.
  • Я видел, как некоторые люди используют опцию altFormat в средстве выбора даты. Не заинтересован в этом подходе, если я могу его избежать, так как он требует создания второго скрытого поля ввода и синхронизации между ними.
  • Я немного нервничаю по поводу переопределения функции val(); Я также был бы открыт для альтернативной функции получения/установки в плагине, такой как mydateVal()
  • Я очень открыт для использования какого-либо другого плагина, который уже существует! Просто сам не нашел...

Помощь?


person yahermann    schedule 25.02.2019    source источник


Ответы (1)


Я совершенно уверен, что мой ответ не такой, как вы ожидаете... Я думаю, что вы слишком усложнили задачу. Когда дело доходит до манипуляций с датами, я всегда использую moment.js. Я действительно думаю, что мой ответ намного проще, чем то, что вы погрузились.

Moment может легко обрабатывать различные форматы даты. Вот простая демонстрация, в которой у вас есть 3 входа, созданные с помощью jQuery-ui datepicker и разных форматов.

Теперь определение форматирования немного отличается между датчиком jQuery-UI и Момент...

Поэтому я использовал 2 data-атрибуты для их хранения. оба. Таким образом, легко установить формат средства выбора даты из разметки HTML. Затем, в функции получения даты ISO, он использует формат момента, чтобы правильно проанализировать его и преобразовать в ISO.

$(document).ready(function() {

  // Instantiate all datepickers with their own format
  $('.mydatepicker').each(function(){
    var format = $(this).data("datepicker_format");
    console.log("Datepicker initialised with format: "+format);
    $(this).datepicker({
      dateFormat : format
    });
  });

  // A button to console log the date conversion to ISO
  $(".getDate").on("click",function(){
    var input = $(this).prev('.mydatepicker');
    
    var date = input.val();
    var format = input.data("moment_format");
    console.log("Date from the input: "+date);

    var iso_date = moment(date,format).format("YYYY-MM-DD");
    console.log("ISO date: "+iso_date);
  });

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css" rel="stylesheet"/>

<input type="text" class="mydatepicker" id="myelement1" value="02/23/2019" data-datepicker_format="mm/dd/yy" data-moment_format="MM/DD/YYYY">
<button class="getDate">Console log the ISO date</button>
<br>
<br>

<input type="text" class="mydatepicker" id="myelement2" value="2019-02-02" data-datepicker_format="yy-mm-dd" data-moment_format="YYYY-MM-DD">
<button class="getDate">Console log the ISO date</button>
<br>
<br>

<input type="text" class="mydatepicker" id="myelement3" value="September 19, 2019" data-datepicker_format="MM dd, yy" data-moment_format="MMM Do, YYYY">
<button class="getDate">Console log the ISO date</button>
<br>
<br>

Пожалуйста, запустите приведенный выше фрагмент кода в полностраничном режиме.

CodePen.


Если вы хотите, чтобы функция вызывалась откуда угодно (вместо кнопки):

function ISO_date(datepicker){
  return moment(datepicker.val(),datepicker.data("moment_format")).format("YYYY-MM-DD");
}

Затем назовите это так:

var convertedDate = ISO_date( $("someSpecificDatePickerSelector") );  // Pass the datepicker element.
person Louys Patrice Bessette    schedule 25.02.2019
comment
Спасибо за вдумчивый и подробный ответ. Основываясь на вашем ответе, я буду использовать moment.js для преобразования. Однако я имею дело с большим количеством устаревшего кода, который получает/устанавливает дату как $("someselector").val() и $("someselector").val('2019-02-24'), поэтому я все еще ищу это. Кроме того, я думаю, что это был бы полезный плагин в целом для локализации дат для каждого пользователя, при этом последовательно передавая/получая даты iso8601 внутри. - person yahermann; 26.02.2019