JAVASCRIPT   68
timepicki
Guest on 13th August 2022 12:44:33 AM


  1. /*
  2.  * Author: @senthil2rajan
  3.  * plugin: timepicker
  4.  * website: senthilraj.github.io/Timepicki
  5.  */
  6. (function($) {
  7.  
  8.         $.fn.timepicki = function(options) {
  9.  
  10.                 var defaults = {
  11.                         format_output: function(tim, mini, meri) {
  12.                                 if(settings.show_meridian){
  13.                                         return tim + " : " + mini + " : " + meri;
  14.                                 }else{
  15.                                         return tim + " : " + mini;
  16.                                 }
  17.                         },
  18.                         increase_direction: 'down',
  19.                         custom_classes: '',
  20.                         min_hour_value: 1,
  21.                         max_hour_value: 12,
  22.                         show_meridian: true,
  23.                         step_size_hours: '1',
  24.                         step_size_minutes: '1',
  25.                         overflow_minutes: false,
  26.                         disable_keyboard_mobile: false,
  27.                         reset: false
  28.                 };
  29.  
  30.                 var settings = $.extend({}, defaults, options);
  31.  
  32.                 return this.each(function() {
  33.  
  34.                         var ele = $(this);
  35.                         var ele_hei = ele.outerHeight();
  36.                         ele_hei += 10;
  37.                         $(ele).wrap("<div class='time_pick'>");
  38.                         var ele_par = $(this).parents(".time_pick");
  39.  
  40.                         // developer can specify which arrow makes the numbers go up or down
  41.                         var top_arrow_button = (settings.increase_direction === 'down') ?
  42.                                 "<div class='prev action-prev'></div>" :
  43.                                 "<div class='prev action-next'></div>";
  44.                         var bottom_arrow_button = (settings.increase_direction === 'down') ?
  45.                                 "<div class='next action-next'></div>" :
  46.                                 "<div class='next action-prev'></div>";
  47.  
  48.                         var new_ele = $(
  49.                                 "<div class='timepicker_wrap " + settings.custom_classes + "'>" +
  50.                                         "<div class='arrow_top'></div>" +
  51.                                         "<div class='time'>" +
  52.                                                 top_arrow_button +
  53.                                                 "<div class='ti_tx'><input type='text' class='timepicki-input'" + (settings.disable_keyboard_mobile ? "readonly" : "") + "></div>" +
  54.                                                 bottom_arrow_button +
  55.                                         "</div>" +
  56.                                         "<div class='mins'>" +
  57.                                                 top_arrow_button +
  58.                                                 "<div class='mi_tx'><input type='text' class='timepicki-input'" + (settings.disable_keyboard_mobile ? "readonly" : "") + "></div>" +
  59.                                                 bottom_arrow_button +
  60.                                         "</div>");
  61.                         if(settings.show_meridian){
  62.                                 new_ele.append(
  63.                                         "<div class='meridian'>" +
  64.                                                 top_arrow_button +
  65.                                                 "<div class='mer_tx'><input type='text' class='timepicki-input' readonly></div>" +
  66.                                                 bottom_arrow_button +
  67.                                         "</div>");
  68.                         }
  69.                         if(settings.reset){
  70.                                 new_ele.append(
  71.                                         "<div><a href='#' class='reset_time'>Reset</a></div>");
  72.                         }
  73.                         ele_par.append(new_ele);
  74.                         var ele_next = $(this).next(".timepicker_wrap");
  75.                         var ele_next_all_child = ele_next.find("div");
  76.                         var inputs = ele_par.find('input');
  77.                        
  78.                         $('.reset_time').on("click", function(event) {
  79.                                 ele.val("");
  80.                                 close_timepicki();
  81.                         });            
  82.                         $(".timepicki-input").keydown( function(keyevent){
  83.                                         var len = $(this).val().length;
  84.  
  85.                                         // Allow: backspace, delete, tab, escape, enter and .
  86.                                         if ($.inArray(keyevent.keyCode, [46, 8, 9, 27, 13, 110, 190]) !== -1 ||
  87.                                              // Allow: Ctrl+A
  88.                                             (keyevent.keyCode == 65 && keyevent.ctrlKey === true) ||
  89.                                              // Allow: home, end, left, right
  90.                                             (keyevent.keyCode >= 35 && keyevent.keyCode <= 39)) {
  91.                                                  // let it happen, don't do anything
  92.                                                  return;
  93.                                         }
  94.                                         // Ensure that it is a number and stop the keypress
  95.                                         if ((keyevent.shiftKey || (keyevent.keyCode < 48 || keyevent.keyCode > 57)) &&
  96.                                         (keyevent.keyCode < 96 || keyevent.keyCode > 105) || len==2 ) {
  97.                                             keyevent.preventDefault();
  98.                                         }
  99.  
  100.                         });
  101.  
  102.                         // open or close time picker when clicking
  103.                         $(document).on("click", function(event) {
  104.                                 if (!$(event.target).is(ele_next) && ele_next.css("display")=="block" && !$(event.target).is($('.reset_time'))) {
  105.                                         if (!$(event.target).is(ele)) {
  106.                                                 set_value(event, !is_element_in_timepicki($(event.target)));
  107.                                         } else {
  108.                                                 var ele_lef =  0;
  109.                                                
  110.                                                 ele_next.css({
  111.                                                         "top": ele_hei + "px",
  112.                                                         "left": ele_lef + "px"
  113.                                                 });
  114.                                                 open_timepicki();
  115.                                         }
  116.                                 }
  117.                         });
  118.  
  119.                         // open the modal when the user focuses on the input
  120.                         ele.on('focus', open_timepicki);
  121.  
  122.                         // select all text in input when user focuses on it
  123.                         inputs.on('focus', function() {
  124.                                 var input = $(this);
  125.                                 if (!input.is(ele)) {
  126.                                         input.select();
  127.                                 }
  128.                         });
  129.  
  130.                         // allow user to increase and decrease numbers using arrow keys
  131.                         inputs.on('keydown', function(e) {
  132.                                 var direction, input = $(this);
  133.  
  134.                                 // UP
  135.                                 if (e.which === 38) {
  136.                                         if (settings.increase_direction === 'down') {
  137.                                                 direction = 'prev';
  138.                                         } else {
  139.                                                 direction = 'next';
  140.                                         }
  141.                                 // DOWN
  142.                                 } else if (e.which === 40) {
  143.                                         if (settings.increase_direction === 'down') {
  144.                                                 direction = 'next';
  145.                                         } else {
  146.                                                 direction = 'prev';
  147.                                         }
  148.                                 }
  149.  
  150.                                 if (input.closest('.timepicker_wrap .time').length) {
  151.                                         change_time(null, direction);
  152.                                 } else if (input.closest('.timepicker_wrap .mins').length) {
  153.                                         change_mins(null, direction);
  154.                                 } else if (input.closest('.timepicker_wrap .meridian').length && settings.show_meridian) {
  155.                                         change_meri(null, direction);
  156.                                 }
  157.                         });
  158.  
  159.                         // close the modal when the time picker loses keyboard focus
  160.                         inputs.on('blur', function() {
  161.                                 setTimeout(function() {
  162.                                         var focused_element = $(document.activeElement);
  163.                                         if (focused_element.is(':input') && !is_element_in_timepicki(focused_element)) {
  164.                                                 set_value();
  165.                                                 close_timepicki();
  166.                                         }
  167.                                 }, 0);
  168.                         });
  169.  
  170.                         function is_element_in_timepicki(jquery_element) {
  171.                                 return $.contains(ele_par[0], jquery_element[0]) || ele_par.is(jquery_element);
  172.                         }
  173.  
  174.                         function set_value(event, close) {
  175.                                 // use input values to set the time
  176.                                 var tim = ele_next.find(".ti_tx input").val();
  177.                                 var mini = ele_next.find(".mi_tx input").val();
  178.                                 var meri = "";
  179.                                 if(settings.show_meridian){
  180.                                         meri = ele_next.find(".mer_tx input").val();
  181.                                 }
  182.                                
  183.                                 if (tim.length !== 0 && mini.length !== 0 && (!settings.show_meridian || meri.length !== 0)) {
  184.                                         // store the value so we can set the initial value
  185.                                         // next time the picker is opened
  186.                                         ele.attr('data-timepicki-tim', tim);
  187.                                         ele.attr('data-timepicki-mini', mini);
  188.                                        
  189.                                         if(settings.show_meridian){
  190.                                                 ele.attr('data-timepicki-meri', meri);
  191.                                                 // set the formatted value
  192.                                                 ele.val(settings.format_output(tim, mini, meri));
  193.                                         }else{
  194.                                                 ele.val(settings.format_output(tim, mini));
  195.                                         }
  196.                                 }
  197.  
  198.                                 if (close) {
  199.                                         close_timepicki();
  200.                                 }
  201.                         }
  202.  
  203.                         function open_timepicki() {
  204.                                 set_date(settings.start_time);
  205.                                 ele_next.fadeIn();
  206.                                 // focus on the first input and select its contents
  207.                                 var first_input = ele_next.find('input:visible').first();
  208.                                 first_input.focus();
  209.                                 // if the user presses shift+tab while on the first input,
  210.                                 // they mean to exit the time picker and go to the previous field
  211.                                 var first_input_exit_handler = function(e) {
  212.                                         if (e.which === 9 && e.shiftKey) {
  213.                                                 first_input.off('keydown', first_input_exit_handler);
  214.                                                 var all_form_elements = $(':input:visible:not(.timepicki-input)');
  215.                                                 var index_of_timepicki_input = all_form_elements.index(ele);
  216.                                                 var previous_form_element = all_form_elements.get(index_of_timepicki_input-1);
  217.                                                 previous_form_element.focus();
  218.                                         }
  219.                                 };
  220.                                 first_input.on('keydown', first_input_exit_handler);
  221.                         }
  222.  
  223.                         function close_timepicki() {
  224.                                 ele_next.fadeOut();
  225.                         }
  226.  
  227.                         function set_date(start_time) {
  228.                                 var d, ti, mi, mer;
  229.  
  230.                                 // if a value was already picked we will remember that value
  231.                                 if (ele.is('[data-timepicki-tim]')) {
  232.                                         ti = Number(ele.attr('data-timepicki-tim'));
  233.                                         mi = Number(ele.attr('data-timepicki-mini'));
  234.                                         if(settings.show_meridian){
  235.                                                 mer = ele.attr('data-timepicki-meri');
  236.                                         }
  237.                                 // developer can specify a custom starting value
  238.                                 } else if (typeof start_time === 'object') {
  239.                                         ti = Number(start_time[0]);
  240.                                         mi = Number(start_time[1]);
  241.                                         if(settings.show_meridian){
  242.                                                 mer = start_time[2];
  243.                                         }
  244.                                 // default is we will use the current time
  245.                                 } else {
  246.                                         d = new Date();
  247.                                         ti = d.getHours();
  248.                                         mi = d.getMinutes();
  249.                                         mer = "AM";
  250.                                         if (12 < ti  && settings.show_meridian) {
  251.                                                 ti -= 12;
  252.                                                 mer = "PM";
  253.                                         }
  254.                                 }
  255.  
  256.                                 if (ti < 10) {
  257.                                         ele_next.find(".ti_tx input").val("0" + ti);
  258.                                 } else {
  259.                                         ele_next.find(".ti_tx input").val(ti);
  260.                                 }
  261.                                 if (mi < 10) {
  262.                                         ele_next.find(".mi_tx input").val("0" + mi);
  263.                                 } else {
  264.                                         ele_next.find(".mi_tx input").val(mi);
  265.                                 }
  266.                                 if(settings.show_meridian){
  267.                                         if (mer < 10) {
  268.                                                 ele_next.find(".mer_tx input").val("0" + mer);
  269.                                         } else {
  270.                                                 ele_next.find(".mer_tx input").val(mer);
  271.                                         }
  272.                                 }
  273.                         }
  274.  
  275.                         function change_time(cur_ele, direction) {
  276.                                 var cur_cli = "time";
  277.                                 var cur_time = Number(ele_next.find("." + cur_cli + " .ti_tx input").val());
  278.                                 var ele_st = Number(settings.min_hour_value);
  279.                                 var ele_en = Number(settings.max_hour_value);
  280.                                 var step_size = Number(settings.step_size_hours);
  281.                                 if ((cur_ele && cur_ele.hasClass('action-next')) || direction === 'next') {
  282.                                         if (cur_time + step_size > ele_en) {
  283.                                                 var min_value = ele_st;
  284.                                                 if (min_value < 10) {
  285.                                                         min_value = '0' + min_value;
  286.                                                 } else {
  287.                                                         min_value = String(min_value);
  288.                                                 }
  289.                                                 ele_next.find("." + cur_cli + " .ti_tx input").val(min_value);
  290.                                         } else {
  291.                                                 cur_time = cur_time + step_size;
  292.                                                 if (cur_time < 10) {
  293.                                                         cur_time = "0" + cur_time;
  294.                                                 }
  295.                                                 ele_next.find("." + cur_cli + " .ti_tx input").val(cur_time);
  296.                                         }
  297.                                 } else if ((cur_ele && cur_ele.hasClass('action-prev')) || direction === 'prev') {
  298.                                         if (cur_time - step_size <= ele_st) {
  299.                                                 var max_value = ele_en;
  300.                                                 if (max_value < 10) {
  301.                                                         max_value = '0' + max_value;
  302.                                                 } else {
  303.                                                         max_value = String(max_value);
  304.                                                 }
  305.                                                 ele_next.find("." + cur_cli + " .ti_tx input").val(max_value);
  306.                                         } else {
  307.                                                 cur_time = cur_time - step_size;
  308.                                                 if (cur_time < 10) {
  309.                                                         cur_time = "0" + cur_time;
  310.                                                 }
  311.                                                 ele_next.find("." + cur_cli + " .ti_tx input").val(cur_time);
  312.                                         }
  313.                                 }
  314.                         }
  315.  
  316.                         function change_mins(cur_ele, direction) {
  317.                                 var cur_cli = "mins";
  318.                                 var cur_mins = Number(ele_next.find("." + cur_cli + " .mi_tx input").val());
  319.                                 var ele_st = 0;
  320.                                 var ele_en = 59;
  321.                                 var step_size = Number(settings.step_size_minutes);
  322.                                 if ((cur_ele && cur_ele.hasClass('action-next')) || direction === 'next') {
  323.                                         if (cur_mins + step_size > ele_en) {
  324.                                                 ele_next.find("." + cur_cli + " .mi_tx input").val("00");
  325.                                                 if(settings.overflow_minutes){
  326.                                                         change_time(null, 'next');
  327.                                                 }
  328.                                         } else {
  329.                                                 cur_mins = cur_mins + step_size;
  330.                                                 if (cur_mins < 10) {
  331.                                                         ele_next.find("." + cur_cli + " .mi_tx input").val("0" + cur_mins);
  332.                                                 } else {
  333.                                                         ele_next.find("." + cur_cli + " .mi_tx input").val(cur_mins);
  334.                                                 }
  335.                                         }
  336.                                 } else if ((cur_ele && cur_ele.hasClass('action-prev')) || direction === 'prev') {
  337.                                         if (cur_mins - step_size <= ele_st) {
  338.                                                 ele_next.find("." + cur_cli + " .mi_tx input").val(ele_en + 1 - step_size);
  339.                                                 if(settings.overflow_minutes){
  340.                                                         change_time(null, 'prev');
  341.                                                 }
  342.                                         } else {
  343.                                                 cur_mins = cur_mins - step_size;
  344.                                                 if (cur_mins < 10) {
  345.                                                         ele_next.find("." + cur_cli + " .mi_tx input").val("0" + cur_mins);
  346.                                                 } else {
  347.                                                         ele_next.find("." + cur_cli + " .mi_tx input").val(cur_mins);
  348.                                                 }
  349.                                         }
  350.                                 }
  351.                         }
  352.  
  353.                         function change_meri(cur_ele, direction) {
  354.                                 var cur_cli = "meridian";
  355.                                 var ele_st = 0;
  356.                                 var ele_en = 1;
  357.                                 var cur_mer = null;
  358.                                 cur_mer = ele_next.find("." + cur_cli + " .mer_tx input").val();
  359.                                 if ((cur_ele && cur_ele.hasClass('action-next')) || direction === 'next') {
  360.                                         if (cur_mer == "AM") {
  361.                                                 ele_next.find("." + cur_cli + " .mer_tx input").val("PM");
  362.                                         } else {
  363.                                                 ele_next.find("." + cur_cli + " .mer_tx input").val("AM");
  364.                                         }
  365.                                 } else if ((cur_ele && cur_ele.hasClass('action-prev')) || direction === 'prev') {
  366.                                         if (cur_mer == "AM") {
  367.                                                 ele_next.find("." + cur_cli + " .mer_tx input").val("PM");
  368.                                         } else {
  369.                                                 ele_next.find("." + cur_cli + " .mer_tx input").val("AM");
  370.                                         }
  371.                                 }
  372.                         }
  373.  
  374.                         // handle clicking on the arrow icons
  375.                         var cur_next = ele_next.find(".action-next");
  376.                         var cur_prev = ele_next.find(".action-prev");
  377.                         $(cur_prev).add(cur_next).on("click", function() {
  378.                                 var cur_ele = $(this);
  379.                                 if (cur_ele.parent().attr("class") == "time") {
  380.                                         change_time(cur_ele);
  381.                                 } else if (cur_ele.parent().attr("class") == "mins") {
  382.                                         change_mins(cur_ele);
  383.                                 } else {
  384.                                         if(settings.show_meridian){
  385.                                                 change_meri(cur_ele);
  386.                                         }
  387.                                 }
  388.                         });
  389.  
  390.                 });
  391.         };
  392.  
  393. }(jQuery));

Raw Paste

Login or Register to edit or fork this paste. It's free.