jquery插件多个实例

时间:2015-06-17 22:57:24

标签: javascript jquery oop

我正在尝试创建一个简单的jQuery插件,该插件允许" timepicker"的多个实例。我过去没有做过很多JavaScript OOP,所以我认为创建这对我来说是一次很棒的学习经历。话虽这么说,我似乎无法弄清楚为什么在我改变时间时所有实例都会受到影响。这是我在StackOverflow上的第一篇文章,所以请耐心等待。 这是代码:



(function($) {

  //Helper functions 
  if (typeof String.prototype.endsWith != 'function') {
    String.prototype.endsWith = function(str) {
      return str.length > 0 && this.substring(this.length - str.length, this.length) === str;
    }
  }

  //Find if area is on the clickable list
  var findOne = function(haystack, arr) {
    return arr.some(function(v) {
      return haystack.indexOf(v) >= 0;
    });
  };

  var Timepicker = function(element, options) {

    this.defaults = {
      now: new Date()
    };
    this.element = $(element);
    this.createTimepicker();
    this.options = $.extend({}, this.defaults, options);
    this.timepicker = $('.wicked-picker'); //The outer portion of the picker
    this.up = $('.wicked-picker__controls__control-up'); //the up control(s)
    this.down = $('.wicked-picker__controls__control-down'); //the down control(s)
    this.hoursElem = $('.wicked-picker__controls__control--hours'); //the hours text
    this.minutesElem = $('.wicked-picker__controls__control--minutes'); //the minutes text
    this.meridiemElem = $('.wicked-picker__controls__control--meridiem'); //the am or pm text
    this.canClick = ['timepicker', this.timepicker.selector.substring(1), this.up.selector.substring(1), this.down.selector.substring(1), this.hoursElem.selector.substring(1), this.minutesElem.selector.substring(1), this.meridiemElem.selector.substring(1)]; //the clickable areas
    this.selectedHour = ((this.defaults.now.getHours() + 11) % 12) + 1; //the default hour
    this.selectedMin = ((this.defaults.now.getMinutes() < 10) ? '0' : '') + this.defaults.now.getMinutes(); //the default minute
    this.selectedMeridiem = (this.defaults.now.getHours > 12) ? 'PM' : 'AM'; //the defaut meridiem
    this.attach(element); //attach events to this element

  };

  $.extend(Timepicker.prototype = {

    showTimepicker: function(element) {
      var timepickerPos = this.element.offset();
      //set time to default time (now)
      this.setText(element);
      //if the timepicker's time differs from the input field's time change it
      if (this.getText(element) !== this.getTime()) {
        var inputTime = this.getText(element).replace(':', '').split(' ');
        var newTime = new Date();
        newTime.setHours(inputTime[0]);
        newTime.setMinutes(inputTime[2]);
        this.setTime(newTime);
      }
      //Positioning
      this.timepicker.css({
        'z-index': this.element.zIndex() + 1,
        position: 'absolute',
        left: timepickerPos.left,
        top: timepickerPos.top + element.target.offsetHeight + 5
      }).show();

      //Time up/down events
      //Most likely the area with issues
      //Needs to know which instance
      $(this.up).on('click', $.proxy(this.changeValue, this, '+', element));
      $(this.down).on('click', $.proxy(this.changeValue, this, '-', element));
    },

    hideTimepicker: function(element) {
      var targetClass = element.target.className.split(' ');
      //Check if area is clickable before hiding
      if (findOne(targetClass, this.canClick) === false) {
        this.timepicker.hide();
      }
    },

    //Create only one timepicker per page
    createTimepicker: function() {
      if ($('.wicked-picker').length === 0)
        $('body').append('<div class="wicked-picker"> <p class="wicked-picker__title">Timepicker</p> <ul class="wicked-picker__controls"> <li class="wicked-picker__controls__control"> <span class="wicked-picker__controls__control-up"></span><span class="wicked-picker__controls__control--hours">00</span><span class="wicked-picker__controls__control-down"></span> </li> <li class="wicked-picker__controls__control"> <span class="wicked-picker__controls__control-up"></span><span class="wicked-picker__controls__control--minutes">00</span><span class="wicked-picker__controls__control-down"></span> </li> <li class="wicked-picker__controls__control"> <span class="wicked-picker__controls__control-up"></span><span class="wicked-picker__controls__control--meridiem">AM</span><span class="wicked-picker__controls__control-down"></span> </li> </ul> </div>');
    },

    //Attach the show and hide picker events
    attach: function(element) {
      $(element).on('focus', $.proxy(this.showTimepicker, this));
      $('body').on('click', $.proxy(this.hideTimepicker, this));
    },

    //set the timepicker's time 
    setTime: function(time) {
      this.setHours(time.getHours());
      this.setMinutes(time.getMinutes());
      this.setMeridiem();
    },

    //get the timepicker's time in the form H : MM : AM || PM
    getTime: function() {
      return [this.getHours + ' : ' + this.getMinutes() + ' ' + this.getMeridiem()];
    },

    //set the timepicker's and input field's hours
    setHours: function(hours) {
      var hour = new Date();
      hour.setHours(hours);
      var hoursText = ((hour.getHours() + 11) % 12) + 1;
      this.hoursElem.text(hoursText);
      this.selectedHour = hoursText;
    },

    //set the timepicker's hours
    getHours: function() {
      var hours = new Date();
      hours.setHours(this.hoursElem.text());
      return hours.getHours();
    },

    //set the timepicker's and input field's minutes
    setMinutes: function(minutes) {
      var minute = new Date();
      minute.setMinutes(minutes);
      var minutesText = minute.getMinutes();
      var min = ((minutesText < 10) ? '0' : '') + minutesText;
      this.minutesElem.text(min);
      this.selectedMin = min;
    },

    //set the timepicker's minutes
    getMinutes: function() {
      var minutes = new Date();
      minutes.setMinutes(this.minutesElem.text());
      var minutesText = minutes.getMinutes();
      return ((minutesText < 10) ? '0' : '') + minutesText;
    },

    //set the timepicker's and input field's meridiem
    setMeridiem: function() {
      var meridiem = this.getMeridiem();
      var newMeridiem = (meridiem === 'PM') ? 'AM' : 'PM';
      this.meridiemElem.text(newMeridiem);
      this.selectedMeridiem = newMeridiem;
    },

    //set the timepicker's meridiem
    getMeridiem: function() {
      return this.meridiemElem.text();
    },

    //change the input field's time based on the arrow selected for each time unit
    //input is the input field to be changed
    //element is the up or down arrow clicked
    //operator is the '+' or '-' sign
    changeValue: function(operator, input, element) {
      var target = (operator === '+') ? element.target.nextSibling : element.target.previousSibling;
      var targetClass = $(target).attr('class');
      if (targetClass.endsWith('hours')) {
        this.setHours(eval(this.getHours() + operator + 1));
      } else if (targetClass.endsWith('minutes')) {
        this.setMinutes(eval(this.getMinutes() + operator + 1));
      } else {
        this.setMeridiem();
      }
      console.log('changed ' + $(input.target).attr('name'));
      this.setText(input);
    },


    //Set the input field's time
    setText: function(input) {
      console.log('set ' + $(input.target).attr('name') + ' to ' + this.selectedHour + ' : ' + this.selectedMin + ' ' + this.selectedMeridiem);
      $(input.target).val(this.selectedHour + ' : ' + this.selectedMin + ' ' + this.selectedMeridiem);
    },

    //Get the input field's time
    getText: function(input) {
      return $(input.target).val();
    }


  });

  //Create timepickers
  $.fn.timepicker = function(options) {
    return this.each(function() {
      new Timepicker(this, options);
    });
  };

}(jQuery));
&#13;
<!DOCTYPE html>
<html>

<head lang="en">
  <meta charset="UTF-8">
  <title></title>
</head>

<body>
  <input type="text" name="event-start-time" id="event-start-time" class="form-input timepicker grid-5" />
  <input type="text" name="event-end-time" id="event-end-time" class="form-input timepicker grid-5" />
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  <script>
    $('.timepicker').timepicker({});
  </script>
</body>

</html>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

我能够通过删除先前的向上和向下事件单击事件处理程序然后重新应用新的单击事件处理程序来解决问题。这是通过改变

来实现的
$(this.up).on('click', $.proxy(this.changeValue, this, '+', element));
$(this.down).on('click', $.proxy(this.changeValue, this, '-', element));

$(this.up).off('click').on('click', $.proxy(this.changeValue, this, '+', element));

$(this.down).off('click').on('click', $.proxy(this.changeValue, this, '-', element));

感谢您的所有建议!

相关问题