Skip to content

Instantly share code, notes, and snippets.

@jittagornp
Last active November 18, 2015 23:42
Show Gist options
  • Save jittagornp/d2b9ac4e6b8935ed08f0 to your computer and use it in GitHub Desktop.
Save jittagornp/d2b9ac4e6b8935ed08f0 to your computer and use it in GitHub Desktop.
ป้องกันการ keyin ที่ไม่ใช่ตัวเลขลง html input text พร้อมทั้ง auto format number รูปแบบ #,###,##0
/**
* @author jittagornp
* create 16/11/2015
*
* require jQuery - https://code.jquery.com/jquery-1.11.3.min.js
* require numeral - https://cdnjs.cloudflare.com/ajax/libs/numeral.js/1.4.5/numeral.min.js
*/
(function (document, $, numeral, SELECTOR) {
$(function () {
var $doc = $(document);
var $selector = $(SELECTOR);
var FORMAT = '#,###,###,###,##0';
function isFullNumberFormat(str) {
if (isPointFormat(str) && isCommaFormat(str)) {
return /^-?\d{1,3}(\,\d{3})+\.\d+$/g.test(str);
}
if (isPointFormat(str)) {
return /^-?\d+\.\d+$/g.test(str);
}
if (isCommaFormat(str)) {
return /^-?\d{1,3}(\,\d{3})+$/g.test(str);
}
return /^\-?\d+$/g.test(str);
}
function isNumberFormat(str) {
if (isPointFormat(str)) {
return /^-?\d+\.\d+$/g.test(str);
}
return /^\-?\d+$/g.test(str);
}
function isPointFormat(str) {
return /\./g.test(str);
}
function isCommaFormat(str) {
return /\,/g.test(str);
}
function isNotNumberFormat(str) {
return str.length
&& !/\.$/.test(str)
&& !/\-$/.test(str)
&& !isNumberFormat(str);
}
function isNumberKeyCode(code) {
return code >= 48 && code <= 57;
}
function isNumpadKeyCode(code) {
return code >= 96 && code <= 105;
}
function isCtrlA(event) {
return event.keyCode === 65 && event.ctrlKey === true;
}
function isCtrlC(event) {
return event.keyCode === 67 && event.ctrlKey === true;
}
function isCtrlV(event) {
return event.keyCode === 86 && event.ctrlKey === true;
}
function isCtrlX(event) {
return event.keyCode === 88 && event.ctrlKey === true;
}
function isRemove(event) {
return event.keyCode === 46 || event.keyCode === 8;
}
function specialKeyCode(event) {
return $.inArray(event.keyCode, [46, 8, 9, 27, 13, 110]) !== -1 ||
isCtrlA(event) ||
isCtrlC(event) ||
isCtrlV(event) ||
isCtrlX(event) ||
(event.keyCode >= 35 && event.keyCode <= 39);
}
function isNotNumberKeyCode(event) {
// Ensure that it is a number and stop the keypress
return (event.shiftKey || !isNumberKeyCode(event.keyCode))
&& !isNumpadKeyCode(event.keyCode);
}
function makeFloatingFormat(str) {
return str.split(/\.(.*?)$/)[1]
.replace(/./g, function (e) {
return '#';
});
}
function format(str) {
if (isPointFormat(str)) {
return numeral(str).format(FORMAT + '.' + makeFloatingFormat(str));
}
return numeral(str).format(FORMAT);
}
function toNumber(str) {
return str.replace(/\,/g, '');
}
function doFormat() {
var $input = $(this);
if(enableFormat($input)){
var val = toNumber($input.val());
if (isNumberFormat(val)) {
$input.val(format(val));
}
}
}
function pasteFormat() {
var $input = $(this);
var val = $input.val();
if (val && !isFullNumberFormat(val)) {
$input.val('');
}
}
function fromFormat() {
var $input = $(this);
var val = toNumber($input.val());
if (isNumberFormat(val)) {
$input.val(val);
}
}
function isNegativeORDot(event) {
return event.keyCode === 189 || event.keyCode === 190;
}
function invalidNegativePosition(event, val) {
return event.keyCode === 189 && /.+\-/g.test(val);
}
function doubleNegativeORDot(val) {
return /(\-\-)+/g.test(val)
|| /(\.\.)+/g.test(val)
|| /(\-\.)+/g.test(val)
|| /(\.\-)+/g.test(val);
}
function cutLast($input, val) {
val && $input.val(val.substr(0, val.length - 1));
}
function enableFormat($el){
return $el.hasClass('number-format');
}
function callback(event, onSpc, onFormat) {
if (specialKeyCode(event)) {
if (isRemove(event)) {
onSpc && onSpc.call(this);
}
if (isCtrlV(event)) {
pasteFormat.call(this);
}
return;
}
var $input = $(this);
var val = $input.val();
if (isNegativeORDot(event)) {
if (invalidNegativePosition(event, val) || doubleNegativeORDot(val)) {
cutLast($input, val);
event.preventDefault();
}
return;
}
if (isNotNumberKeyCode(event)) {
event.preventDefault();
return;
}
val = toNumber($input.val());
if (isNotNumberFormat(val)) {
cutLast($input, val);
event.preventDefault();
return;
}
if(enableFormat($input)){
onFormat && onFormat.call(this, val);
}
}
$doc.on(
'keydown',
SELECTOR,
callback
).on(
'keyup',
SELECTOR,
function (event) {
callback.call(this, event, doFormat, function (val) {
$(this).val(format(val));
});
}
).on(
'submit',
'form',
function () {
$(this).find(SELECTOR).each(fromFormat);
}
);
$selector.each(doFormat);
});
})(document, jQuery, numeral, 'input[type="text"].input-number');
@jittagornp
Copy link
Author

ปัญหาที่ไม่ใช้ input="number" เพราะ

  1. มันทำ number format ไม่ได้ (user ขอเวลาพิมพ์ให้ format ตัวเลขให้ด้วย)
  2. มันพิมพ์ตัว e ได้ ครับ

@jittagornp
Copy link
Author

jQuery plugin มีแก้ปัญหานี้ไว้ครับ
แต่ UX ไม่ดี คือ
ไม่ใช่ป้องกันการพิมพ์ แต่เป็นการพิมพ์ไปแล้วตัดออก
code ชุดนี้คือห้ามพิมพ์เลย อาจจะไม่ได้ทุกกรณีครับ แต่ก็น่าจะดีกว่าของ jQuery plugin ที่เคยเห็น

@phitak
Copy link

phitak commented Nov 17, 2015

ขอบคุณครับ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment