我正在尝试创建一个简单的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;
答案 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));
感谢您的所有建议!