Monkeypatching jQuery UI Datepicker
Wie im letzten Monkeypatching Blogpost beschrieben gibt es im Projektalltag Anforderungen, die sich mit Standard Tools nicht lösen lassen. Im aktuellen Fall war es nötig zwei Instanzen von jQuery UI Datepicker zu "verbinden" um auf einer Hotelsuchmaschine das Anreise / Abreise Datum zu setzen.
Grundsätzlich eine Funktionalität die von jQuery UI Datepicker bereitgestellt wird, allerdings nur für das Kalender Overlay, nicht jedoch wenn ein Benutzer Freitext Eingaben in den zugehörigen Eingabefeldern macht. Da wir die Synchronisations-Logik bereit im onSelect Callback abgebildet haben, war es wünschenswert, dass der Callback auf dann gerufen wird so bald der Benutzer die Werte der Eingabefelder verändert. Um dies zu erreichen war es wieder nötig tief in den Quellcode von jQuery UI einzugreifen und eine interne Methode zu überschreiben, in diesem Fall $.datepicker._doKeyUp.
$.datepicker._doKeyUp = function(event) { var inst = $.datepicker._getInst(event.target); if (inst.input.val() != inst.lastVal) { try { var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), (inst.input ? inst.input.val() : null), $.datepicker._getFormatConfig(inst)); if (date) { // only if valid $.datepicker._setDateFromField(inst); $.datepicker._updateAlternate(inst); $.datepicker._updateDatepicker(inst);<p>var onSelect = $.datepicker._get(inst, 'onSelect'); if (onSelect) { var dateStr = $.datepicker._formatDate(inst);</p><p>// trigger custom callback onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); } } } catch (err) { $.datepicker.log(err); } } return true;};</p>
Ergebnis ist nun dass der onSelect Callback auch auf Änderungen an den Eingabefeldern reagiert. Allerdings etwas zu "sensibel" so wird der Callback auch dann gerufen wenn das eingebene Datum nicht der Spezifikation entspricht, in unserem Fall möchten wir nur auf ein Datum im Format 01.01.2014 reagieren, der Callback würde aber auch schon feuern, wenn der Benutzer 01.01.20 eingibt (was als 01.01.2020 von jQuery UI interpretiert wird). Die Lösung ist zwar nicht optimal, funktioniert dennoch einwandfrei. Im onSelect Callback prüfen wir einfach das übergebene Datum mit der Eingabe des Users. Stimmt dies nicht überein gehen wir davon aus, dass das Datum nicht der Konvention entspricht und brechen die Bearbeitung ab.
onSelect: function(dateText, inst){ // allow only years with 4 digits (as the user entered in the form field) var inp1 = $(this).val().split('.'); var inp2 = dateText.split('.'); if(inp1[2] != inp2[2]) { return; }<p>// synchronise calendars...}</p>