Reputation: 5232
I am a fan of the timepicker from this SO answer but can't get it to work in a project where input
elements are created dynamically. Problem seems that this timepicker needs to store the object returned by the constructor. Ideally, timepicker should work like the datepicker from jQuery-UI. So I tried to be clever and before creating a jQuery plugin I tried to make a javascript class like this:
function MyTimePicker(inputelement) {
// store the timepicker object
this.mytimepicker = new TimePicker(inputelement);
// show picked time in the element
this.mytimepicker.on('change', function (evt) {
var value = (evt.hour || '00') + ':' + (evt.minute || '00');
evt.element.value = value;
});
}
and use it like this on three input elements:
var dummy1;
var dummy2;
var dummy3;
window.onload = function () {
dummy1 = new MyTimePicker(jQuery('#time2').get(0));
dummy2 = new MyTimePicker(jQuery('#time3').get(0));
dummy3 = new MyTimePicker(jQuery('#time4').get(0));
};
It doesn't work. The timepicker popup appears when clicking in each of the input elements, but the on(change)
event is never called so that the picked time does not show in the input element.
Either because of not having enough experience with Javascript objects, or with using this timepicker.
Update: I improved my code with a proper prototype, here is the complete code, completely standalone to play with:
<!DOCTYPE html>
<html>
<head>
<title>Timepicker class, standalone, by Jonatas Walker</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>
<!-- source: https://github.com/jonataswalker/timepicker.js SO: https://stackoverflow.com/a/36758501/1845672 -->
<link href="//cdn.jsdelivr.net/timepicker.js/latest/timepicker.min.css" rel="stylesheet">
<script src="//cdn.jsdelivr.net/timepicker.js/latest/timepicker.min.js"></script>
</head>
<body>
<div id="arrayoftimes">
<input id="time2" type="time" placeholder="Time HH:MM"><br />
<input id="time3" type="time" placeholder="Time HH:MM"><br />
<input id="time4" type="time" placeholder="Time HH:MM"><br />
</div>
<script>
// Javascript Class. this disturbs the above reference application of TimePicker. It probably is not re-entrant.
//constructor
function MyTimePicker(selector) {
this.mytimepicker;
this.init(selector);
}
//prototype
MyTimePicker.prototype = {
init: function (selector) {
var inputelement = jQuery(selector).get(0);
this.mytimepicker = new TimePicker(inputelement);
// show picked time in the element
this.mytimepicker.on('change', function (evt) {
var value = (evt.hour || '00') + ':' + (evt.minute || '00');
evt.element.value = value;
});
}
};
</script>
<script>
var dummy1;
var dummy2;
var dummy3;
window.onload = function () {
dummy1 = new MyTimePicker('#time2');
dummy2 = new MyTimePicker('#time3');
dummy3 = new MyTimePicker('#time4');
};
</script>
</body>
</html>
Now the first input element works OK, but the picked time value goes into all three input elements. The other two inputs do show the timepicker dialog, but the picked value does not appear.
In the Firebug console, after picking the first time, I see two errors in the timepicker.js: TypeError: active is undefined.
Could that indicate that, somehow, the timepicker internal code is not re-entrant?
Or am I doing something wrong with object oriented javascript?
Update:
I am pretty sure that there is a bug in timepicker.js. I will report here as soon as I find it.
Upvotes: 1
Views: 290
Reputation: 5232
With gforce301 helping me to read the docs, I came to this solution to turn the timepicker into a jQuery plugin. This code has test code and is stand-alone, and contains checkboxes to select or deselect inputs for the timepicker.
The plugin is at the end of this code.
Working: you can add more inputs with the timepicker. Test this with selecting more checkboxes.
Not working: you cannot remove a timepicker from an input. If you deselect a checkbox, the related input will not be listed in the new target list passed to the setTarget()
method, but the timepicker keeps working on the deselected input.
<!DOCTYPE html>
<html>
<head>
<title>Test of Timepicker class, standalone, by Jonatas Walker</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>
<!-- source: https://github.com/jonataswalker/timepicker.js SO: https://stackoverflow.com/a/36758501/1845672 -->
<link href="http://cdn.jsdelivr.net/timepicker.js/latest/timepicker.min.css" rel="stylesheet">
<script src="http://cdn.jsdelivr.net/timepicker.js/latest/timepicker.min.js"></script>
<style>
.timepicker {background-color: yellow;}
</style>
</head>
<body>
<div id="arrayoftimes">
Time 1
<input type="checkbox" onclick="settimeclass(this, '#time1')" />
<input id="time1" type="text" placeholder="Time HH:MM"/>
<br />
Time 2
<input type="checkbox" onclick="settimeclass(this, '#time2')" />
<input id="time2" type="text" placeholder="Time HH:MM"/>
<br />
Time 3
<input type="checkbox" onclick="settimeclass(this, '#time3')" />
<input id="time3" type="text" placeholder="Time HH:MM"/>
<br />
<br />
ID's with timepicker: <span id='msg'></span>
</div>
<script> //this code is specific for this particular page
// at page load, uncheck all checkboxes
$('input:checkbox').prop('checked', false);
$('input:text').val('');
// when (un)checking a checkbox, adjust the timepicker class on each time input
function settimeclass(self, id){
if ($(self).prop('checked')){
$(id).addClass('timepicker');
}else{
$(id).removeClass('timepicker');
}
// apply the new jquery plugin for the timepicker
$('.timepicker').timepicker();
}
</script>
<script> // this code could be moved to a library
// jquery plugin for Jonatas's timepicker
(function ( $ ) {
// create time picker object
var _timepickerobj = new TimePicker([]);//([...], {lang:'en', theme:'dark'});
// attach event for formatting the time
_timepickerobj.on('change', function(evt) {
var value = (evt.hour || '00') + ':' + (evt.minute || '00');
evt.element.value = value;
});
// set timepicker target to jquery selector
$.fn.timepicker = function() {
var sel_array = this.toArray();
//_timepickerobj.target = [];// no effect
_timepickerobj.setTarget(sel_array);
// debugging: list time input id's with timepicker
var sel_ids = $.map(sel_array ,function(sel) {return sel.id;});
$('#msg').text(sel_ids);
return this;
}
}( jQuery ));
</script>
</body>
</html>
This plugin is good enough for my project, but it would be nice if someone could improve, e.g. on removing a timepicker from an input.
Upvotes: 0