如何通过 javascript 中的键盘直接在输入中插入数字?
How to insert a number directally in a input through a keypad in javascript?
我对this plugin有点困惑。有没有办法直接在我的 text-basic
输入中插入数字,而不是在键盘上按 "Done"?我希望当我在键盘中输入数字时,它们会自动显示在 text-basic
输入中(因为直到现在,必须在键盘输入中预览并按回车键才能显示它们)。
代码如下:
/**
* jQuery.NumPad
*
* Copyright (c) 2015 Andrej Kabachnik
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* https://github.com/kabachello/jQuery.NumPad
*
* Version: 1.4
*
*/
(function($){
// From
var cursorFocus = function(elem) {
var x = window.scrollX, y = window.scrollY;
elem.focus();
window.scrollTo(x, y);
}
$.fn.numpad=function(options){
if (typeof options == 'string'){
var nmpd = $.data(this[0], 'numpad');
if (!nmpd) throw "Cannot perform '" + options + "' on a numpad prior to initialization!";
switch (options){
case 'open':
nmpd.open(nmpd.options.target ? nmpd.options.target : this.first());
break;
case 'close':
nmpd.open(nmpd.options.target ? nmpd.options.target : this.first());
break;
}
return this;
}
// Apply the specified options overriding the defaults
options = $.extend({}, $.fn.numpad.defaults, options);
// Create a numpad. One for all elements in this jQuery selector.
// Since numpad() can be called on multiple elements on one page, each call will create a unique numpad id.
var id = 'nmpd' + ($('.nmpd-wrapper').length + 1);
var nmpd = {};
return this.each(function(){
// If an element with the generated unique numpad id exists, the numpad had been instantiated already.
// Otherwise create a new one!
if ($('#'+id).length == 0) {
/** @var nmpd jQuery object containing the entire numpad */
nmpd = $('<div id="' + id + '"></div>').addClass('nmpd-wrapper');
nmpd.options = options;
/** @var display jQuery object representing the display of the numpad (typically an input field) */
var display = $(options.displayTpl).addClass('nmpd-display');
nmpd.display = display;
/** @var grid jQuery object containing the grid for the numpad: the display, the buttons, etc. */
var table = $(options.gridTpl).addClass('nmpd-grid');
nmpd.grid = table;
table.append($(options.rowTpl).append($(options.displayCellTpl).append(display).append($('<input type="hidden" class="dirty" value="0"></input>'))));
// Create rows and columns of the the grid with appropriate buttons
table.append(
$(options.rowTpl)
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(7).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(8).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(9).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonFunctionTpl).html(options.textDelete).addClass('del').click(function(){
nmpd.setValue(nmpd.getValue().toString().substring(0,nmpd.getValue().toString().length - 1));
})))
).append(
$(options.rowTpl)
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(4).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(5).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(6).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonFunctionTpl).html(options.textClear).addClass('clear').click(function(){
nmpd.setValue('');
})))
).append(
$(options.rowTpl)
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(1).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(2).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(3).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonFunctionTpl).html(options.textCancel).addClass('cancel').click(function(){
nmpd.close(false);
})))
).append(
$(options.rowTpl)
.append($(options.cellTpl).append($(options.buttonFunctionTpl).html('±').addClass('neg').click(function(){
nmpd.setValue(nmpd.getValue() * (-1));
})))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(0).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonFunctionTpl).html(options.decimalSeparator).addClass('sep').click(function(){
nmpd.setValue(nmpd.getValue().toString() + options.decimalSeparator);
})))
.append($(options.cellTpl).append($(options.buttonFunctionTpl).html(options.textDone).addClass('done')))
);
// Create the backdrop of the numpad - an overlay for the main page
nmpd.append($(options.backgroundTpl).addClass('nmpd-overlay').click(function(){nmpd.close(false);}));
// Append the grid table to the nmpd element
nmpd.append(table);
// Hide buttons to be hidden
if (options.hidePlusMinusButton){
nmpd.find('.neg').hide();
}
if (options.hideDecimalButton){
nmpd.find('.sep').hide();
}
// Attach events
if (options.onKeypadCreate){
nmpd.on('numpad.create', options.onKeypadCreate);
}
if (options.onKeypadOpen){
nmpd.on('numpad.open', options.onKeypadOpen);
}
if (options.onKeypadClose){
nmpd.on('numpad.close', options.onKeypadClose);
}
if (options.onChange){
nmpd.on('numpad.change', options.onChange);
}
(options.appendKeypadTo ? options.appendKeypadTo : $(document.body)).append(nmpd);
// Special event for the numeric buttons
$('#'+id+' .numero').bind('click', function(){
var val;
if ($('#'+id+' .dirty').val() == '0'){
val = $(this).text();
} else {
val = nmpd.getValue() ? nmpd.getValue().toString() + $(this).text() : $(this).text();
}
nmpd.setValue(val);
});
// Finally, once the numpad is completely instantiated, trigger numpad.create
nmpd.trigger('numpad.create');
} else {
// If the numpad was already instantiated previously, just load it into the nmpd variable
//nmpd = $('#'+id);
//nmpd.display = $('#'+id+' input.nmpd-display');
}
$.data(this, 'numpad', nmpd);
// Make the target element readonly and save the numpad id in the data-numpad property. Also add the special nmpd-target CSS class.
$(this).attr("readonly", true).attr('data-numpad', id).addClass('nmpd-target');
// Register a listener to open the numpad on the event specified in the options
$(this).bind(options.openOnEvent,function(){
nmpd.open(options.target ? options.target : $(this));
});
// Define helper functions
/**
* Gets the current value displayed in the numpad
* @return string | number
*/
nmpd.getValue = function(){
return isNaN(nmpd.display.val()) ? 0 : nmpd.display.val();
};
/**
* Sets the display value of the numpad
* @param string value
* @return jQuery object nmpd
*/
nmpd.setValue = function(value){
if (nmpd.display.attr('maxLength') < value.toString().length) value = value.toString().substr(0, nmpd.display.attr('maxLength'));
nmpd.display.val(value);
nmpd.find('.dirty').val('1');
nmpd.trigger('numpad.change', [value]);
return nmpd;
};
/**
* Closes the numpad writing it's value to the given target element
* @param jQuery object target
* @return jQuery object nmpd
*/
nmpd.close = function(target){
// If a target element is given, set it's value to the dipslay value of the numpad. Otherwise just hide the numpad
if (target){
if (target.prop("tagName") == 'INPUT'){
target.val(nmpd.getValue().toString().replace('.', options.decimalSeparator));
} else {
target.html(nmpd.getValue().toString().replace('.', options.decimalSeparator));
}
}
// Hide the numpad and trigger numpad.close
nmpd.hide();
nmpd.trigger('numpad.close');
// Trigger a change event on the target element if the value has really been changed
// TODO check if the value has really been changed!
if (target && target.prop("tagName") == 'INPUT'){
target.trigger('change');
}
return nmpd;
};
/**
* Opens the numpad for a given target element optionally filling it with a given value
* @param jQuery object target
* @param string initialValue
* @return jQuery object nmpd
*/
nmpd.open = function(target, initialValue){
// Set the initial value
// Use nmpd.display.val to avoid triggering numpad.change for the initial value
if (initialValue){
nmpd.display.val(initialValue);
} else {
if (target.prop("tagName") == 'INPUT'){
nmpd.display.val(target.val());
nmpd.display.attr('maxLength', target.attr('maxLength'));
} else {
nmpd.display.val(parseFloat(target.text()));
}
}
// Mark the numpad as not dirty initially
$('#'+id+' .dirty').val(0);
// Show the numpad and position it on the page
cursorFocus(nmpd.show().find('.cancel'));
position(nmpd.find('.nmpd-grid'), options.position, options.positionX, options.positionY);
// Register a click handler on the done button to update the target element
// Make sure all other click handlers get removed. Otherwise some unwanted sideeffects may occur if the numpad is
// opened multiple times for some reason
$('#'+id+' .done').off('click');
$('#'+id+' .done').one('click', function(){ nmpd.close(target); });
// Finally trigger numpad.open
nmpd.trigger('numpad.open');
return nmpd;
};
});
};
/**
* Positions any given jQuery element within the page
*/
function position(element, mode, posX, posY) {
var x = 0;
var y = 0;
if (mode == 'fixed'){
element.css('position','fixed');
if (posX == 'left'){
x = 0;
} else if (posX == 'right'){
x = $(window).width() - element.outerWidth();
} else if (posX == 'center'){
x = ($(window).width() / 2) - (element.outerWidth() / 2);
} else if ($.type(posX) == 'number'){
x = posX;
}
element.css('left', x);
if (posY == 'top'){
y = 0;
} else if (posY == 'bottom'){
y = $(window).height() - element.outerHeight();
} else if (posY == 'middle'){
y = ($(window).height() / 2) - (element.outerHeight() / 2);
} else if ($.type(posY) == 'number'){
y = posY;
}
element.css('top', y);
}
return element;
}
// Default values for numpad options
$.fn.numpad.defaults = {
target: false,
openOnEvent: 'click',
backgroundTpl: '<div></div>',
gridTpl: '<table></table>',
displayTpl: '<input type="text" />',
displayCellTpl: '<td colspan="4"></td>',
rowTpl: '<tr></tr>',
cellTpl: '<td></td>',
buttonNumberTpl: '<button></button>',
buttonFunctionTpl: '<button></button>',
gridTableClass: '',
hidePlusMinusButton: false,
hideDecimalButton: false,
textDone: 'Done',
textDelete: 'Del',
textClear: 'Clear',
textCancel: 'Cancel',
decimalSeparator: ',',
precision: null,
appendKeypadTo: false,
position: 'fixed',
positionX: 'center',
positionY: 'middle',
onKeypadCreate: false,
onKeypadOpen: false,
onKeypadClose: false,
onChange: false
};
})(jQuery);
$('#text-basic').numpad();
.nmpd-wrapper {display: none;}
.nmpd-target {cursor: pointer;}
.nmpd-grid {position:absolute; left:50px; top:50px; z-index:5000; -khtml-user-select: none; border-radius:10px; padding:10px; width: initial;}
.nmpd-overlay {z-index:4999;}
input.nmpd-display {text-align: right;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="text-basic" placeholder="Click to show numpad">
[更新]
您只需要将此选项添加到初始化中即可。无需编辑插件代码:
$('#text-basic').numpad({
onChange: (e,value)=>$("#text-basic").val( value )
});
我对this plugin有点困惑。有没有办法直接在我的 text-basic
输入中插入数字,而不是在键盘上按 "Done"?我希望当我在键盘中输入数字时,它们会自动显示在 text-basic
输入中(因为直到现在,必须在键盘输入中预览并按回车键才能显示它们)。
代码如下:
/**
* jQuery.NumPad
*
* Copyright (c) 2015 Andrej Kabachnik
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* https://github.com/kabachello/jQuery.NumPad
*
* Version: 1.4
*
*/
(function($){
// From
var cursorFocus = function(elem) {
var x = window.scrollX, y = window.scrollY;
elem.focus();
window.scrollTo(x, y);
}
$.fn.numpad=function(options){
if (typeof options == 'string'){
var nmpd = $.data(this[0], 'numpad');
if (!nmpd) throw "Cannot perform '" + options + "' on a numpad prior to initialization!";
switch (options){
case 'open':
nmpd.open(nmpd.options.target ? nmpd.options.target : this.first());
break;
case 'close':
nmpd.open(nmpd.options.target ? nmpd.options.target : this.first());
break;
}
return this;
}
// Apply the specified options overriding the defaults
options = $.extend({}, $.fn.numpad.defaults, options);
// Create a numpad. One for all elements in this jQuery selector.
// Since numpad() can be called on multiple elements on one page, each call will create a unique numpad id.
var id = 'nmpd' + ($('.nmpd-wrapper').length + 1);
var nmpd = {};
return this.each(function(){
// If an element with the generated unique numpad id exists, the numpad had been instantiated already.
// Otherwise create a new one!
if ($('#'+id).length == 0) {
/** @var nmpd jQuery object containing the entire numpad */
nmpd = $('<div id="' + id + '"></div>').addClass('nmpd-wrapper');
nmpd.options = options;
/** @var display jQuery object representing the display of the numpad (typically an input field) */
var display = $(options.displayTpl).addClass('nmpd-display');
nmpd.display = display;
/** @var grid jQuery object containing the grid for the numpad: the display, the buttons, etc. */
var table = $(options.gridTpl).addClass('nmpd-grid');
nmpd.grid = table;
table.append($(options.rowTpl).append($(options.displayCellTpl).append(display).append($('<input type="hidden" class="dirty" value="0"></input>'))));
// Create rows and columns of the the grid with appropriate buttons
table.append(
$(options.rowTpl)
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(7).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(8).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(9).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonFunctionTpl).html(options.textDelete).addClass('del').click(function(){
nmpd.setValue(nmpd.getValue().toString().substring(0,nmpd.getValue().toString().length - 1));
})))
).append(
$(options.rowTpl)
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(4).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(5).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(6).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonFunctionTpl).html(options.textClear).addClass('clear').click(function(){
nmpd.setValue('');
})))
).append(
$(options.rowTpl)
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(1).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(2).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(3).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonFunctionTpl).html(options.textCancel).addClass('cancel').click(function(){
nmpd.close(false);
})))
).append(
$(options.rowTpl)
.append($(options.cellTpl).append($(options.buttonFunctionTpl).html('±').addClass('neg').click(function(){
nmpd.setValue(nmpd.getValue() * (-1));
})))
.append($(options.cellTpl).append($(options.buttonNumberTpl).html(0).addClass('numero')))
.append($(options.cellTpl).append($(options.buttonFunctionTpl).html(options.decimalSeparator).addClass('sep').click(function(){
nmpd.setValue(nmpd.getValue().toString() + options.decimalSeparator);
})))
.append($(options.cellTpl).append($(options.buttonFunctionTpl).html(options.textDone).addClass('done')))
);
// Create the backdrop of the numpad - an overlay for the main page
nmpd.append($(options.backgroundTpl).addClass('nmpd-overlay').click(function(){nmpd.close(false);}));
// Append the grid table to the nmpd element
nmpd.append(table);
// Hide buttons to be hidden
if (options.hidePlusMinusButton){
nmpd.find('.neg').hide();
}
if (options.hideDecimalButton){
nmpd.find('.sep').hide();
}
// Attach events
if (options.onKeypadCreate){
nmpd.on('numpad.create', options.onKeypadCreate);
}
if (options.onKeypadOpen){
nmpd.on('numpad.open', options.onKeypadOpen);
}
if (options.onKeypadClose){
nmpd.on('numpad.close', options.onKeypadClose);
}
if (options.onChange){
nmpd.on('numpad.change', options.onChange);
}
(options.appendKeypadTo ? options.appendKeypadTo : $(document.body)).append(nmpd);
// Special event for the numeric buttons
$('#'+id+' .numero').bind('click', function(){
var val;
if ($('#'+id+' .dirty').val() == '0'){
val = $(this).text();
} else {
val = nmpd.getValue() ? nmpd.getValue().toString() + $(this).text() : $(this).text();
}
nmpd.setValue(val);
});
// Finally, once the numpad is completely instantiated, trigger numpad.create
nmpd.trigger('numpad.create');
} else {
// If the numpad was already instantiated previously, just load it into the nmpd variable
//nmpd = $('#'+id);
//nmpd.display = $('#'+id+' input.nmpd-display');
}
$.data(this, 'numpad', nmpd);
// Make the target element readonly and save the numpad id in the data-numpad property. Also add the special nmpd-target CSS class.
$(this).attr("readonly", true).attr('data-numpad', id).addClass('nmpd-target');
// Register a listener to open the numpad on the event specified in the options
$(this).bind(options.openOnEvent,function(){
nmpd.open(options.target ? options.target : $(this));
});
// Define helper functions
/**
* Gets the current value displayed in the numpad
* @return string | number
*/
nmpd.getValue = function(){
return isNaN(nmpd.display.val()) ? 0 : nmpd.display.val();
};
/**
* Sets the display value of the numpad
* @param string value
* @return jQuery object nmpd
*/
nmpd.setValue = function(value){
if (nmpd.display.attr('maxLength') < value.toString().length) value = value.toString().substr(0, nmpd.display.attr('maxLength'));
nmpd.display.val(value);
nmpd.find('.dirty').val('1');
nmpd.trigger('numpad.change', [value]);
return nmpd;
};
/**
* Closes the numpad writing it's value to the given target element
* @param jQuery object target
* @return jQuery object nmpd
*/
nmpd.close = function(target){
// If a target element is given, set it's value to the dipslay value of the numpad. Otherwise just hide the numpad
if (target){
if (target.prop("tagName") == 'INPUT'){
target.val(nmpd.getValue().toString().replace('.', options.decimalSeparator));
} else {
target.html(nmpd.getValue().toString().replace('.', options.decimalSeparator));
}
}
// Hide the numpad and trigger numpad.close
nmpd.hide();
nmpd.trigger('numpad.close');
// Trigger a change event on the target element if the value has really been changed
// TODO check if the value has really been changed!
if (target && target.prop("tagName") == 'INPUT'){
target.trigger('change');
}
return nmpd;
};
/**
* Opens the numpad for a given target element optionally filling it with a given value
* @param jQuery object target
* @param string initialValue
* @return jQuery object nmpd
*/
nmpd.open = function(target, initialValue){
// Set the initial value
// Use nmpd.display.val to avoid triggering numpad.change for the initial value
if (initialValue){
nmpd.display.val(initialValue);
} else {
if (target.prop("tagName") == 'INPUT'){
nmpd.display.val(target.val());
nmpd.display.attr('maxLength', target.attr('maxLength'));
} else {
nmpd.display.val(parseFloat(target.text()));
}
}
// Mark the numpad as not dirty initially
$('#'+id+' .dirty').val(0);
// Show the numpad and position it on the page
cursorFocus(nmpd.show().find('.cancel'));
position(nmpd.find('.nmpd-grid'), options.position, options.positionX, options.positionY);
// Register a click handler on the done button to update the target element
// Make sure all other click handlers get removed. Otherwise some unwanted sideeffects may occur if the numpad is
// opened multiple times for some reason
$('#'+id+' .done').off('click');
$('#'+id+' .done').one('click', function(){ nmpd.close(target); });
// Finally trigger numpad.open
nmpd.trigger('numpad.open');
return nmpd;
};
});
};
/**
* Positions any given jQuery element within the page
*/
function position(element, mode, posX, posY) {
var x = 0;
var y = 0;
if (mode == 'fixed'){
element.css('position','fixed');
if (posX == 'left'){
x = 0;
} else if (posX == 'right'){
x = $(window).width() - element.outerWidth();
} else if (posX == 'center'){
x = ($(window).width() / 2) - (element.outerWidth() / 2);
} else if ($.type(posX) == 'number'){
x = posX;
}
element.css('left', x);
if (posY == 'top'){
y = 0;
} else if (posY == 'bottom'){
y = $(window).height() - element.outerHeight();
} else if (posY == 'middle'){
y = ($(window).height() / 2) - (element.outerHeight() / 2);
} else if ($.type(posY) == 'number'){
y = posY;
}
element.css('top', y);
}
return element;
}
// Default values for numpad options
$.fn.numpad.defaults = {
target: false,
openOnEvent: 'click',
backgroundTpl: '<div></div>',
gridTpl: '<table></table>',
displayTpl: '<input type="text" />',
displayCellTpl: '<td colspan="4"></td>',
rowTpl: '<tr></tr>',
cellTpl: '<td></td>',
buttonNumberTpl: '<button></button>',
buttonFunctionTpl: '<button></button>',
gridTableClass: '',
hidePlusMinusButton: false,
hideDecimalButton: false,
textDone: 'Done',
textDelete: 'Del',
textClear: 'Clear',
textCancel: 'Cancel',
decimalSeparator: ',',
precision: null,
appendKeypadTo: false,
position: 'fixed',
positionX: 'center',
positionY: 'middle',
onKeypadCreate: false,
onKeypadOpen: false,
onKeypadClose: false,
onChange: false
};
})(jQuery);
$('#text-basic').numpad();
.nmpd-wrapper {display: none;}
.nmpd-target {cursor: pointer;}
.nmpd-grid {position:absolute; left:50px; top:50px; z-index:5000; -khtml-user-select: none; border-radius:10px; padding:10px; width: initial;}
.nmpd-overlay {z-index:4999;}
input.nmpd-display {text-align: right;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="text-basic" placeholder="Click to show numpad">
[更新]
您只需要将此选项添加到初始化中即可。无需编辑插件代码:
$('#text-basic').numpad({
onChange: (e,value)=>$("#text-basic").val( value )
});