shafafiyat/static/assets/js/number-formatter.js

144 lines
4.3 KiB
JavaScript

/**
* Number Formatter Utility
* Formats numbers with comma separators for better readability
*/
// Format number with comma separators (e.g., 1234567 -> 1,234,567)
function formatNumber(num) {
if (!num) return '';
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
// Remove comma separators from formatted number
function unformatNumber(str) {
if (!str) return '';
return str.replace(/,/g, '');
}
// Extract only digits from any string
function extractDigits(str) {
if (!str) return '';
return str.replace(/\D/g, '');
}
// Initialize number formatting for specified input selectors
function initNumberFormatting(selectors) {
if (typeof $ === 'undefined') {
console.warn('jQuery not found. Number formatting requires jQuery.');
return;
}
$(document).ready(function() {
selectors.forEach(function(selector) {
// Store cursor position to maintain it after formatting
function setCursorPosition(input, pos) {
if (input.setSelectionRange) {
input.setSelectionRange(pos, pos);
}
}
$(selector).on('input', function(e) {
let input = $(this);
let inputElement = this;
let value = input.val();
let cursorPos = inputElement.selectionStart;
// Extract only digits
let digitsOnly = extractDigits(value);
// Store raw value
input.attr('data-raw-value', digitsOnly);
// Format and set the value
let formattedValue = formatNumber(digitsOnly);
input.val(formattedValue);
// Adjust cursor position
let oldLength = value.length;
let newLength = formattedValue.length;
let newCursorPos = cursorPos + (newLength - oldLength);
// Make sure cursor position is valid
if (newCursorPos < 0) newCursorPos = 0;
if (newCursorPos > newLength) newCursorPos = newLength;
// Set cursor position after a short delay
setTimeout(function() {
setCursorPosition(inputElement, newCursorPos);
}, 1);
});
// Handle paste events
$(selector).on('paste', function(e) {
let input = $(this);
setTimeout(function() {
let value = input.val();
let digitsOnly = extractDigits(value);
input.attr('data-raw-value', digitsOnly);
input.val(formatNumber(digitsOnly));
}, 1);
});
});
// Before form submission, replace formatted values with raw values
$('form').on('submit', function() {
selectors.forEach(function(selector) {
let input = $(selector);
let rawValue = input.attr('data-raw-value');
if (rawValue) {
input.val(rawValue);
}
});
});
});
}
// Helper function to get raw value from formatted input
function getRawValue(input) {
return $(input).attr('data-raw-value') || unformatNumber($(input).val());
}
// Helper function to set raw value before AJAX submission
function setRawValuesForSubmission(selectors) {
selectors.forEach(function(selector) {
let input = $(selector);
let rawValue = input.attr('data-raw-value');
if (rawValue) {
input.val(rawValue);
}
});
}
// Helper function to restore formatted values after AJAX submission
function restoreFormattedValues(selectors) {
selectors.forEach(function(selector) {
let input = $(selector);
let rawValue = input.attr('data-raw-value');
if (rawValue) {
input.val(formatNumber(rawValue));
}
});
}
// Auto-initialize for common amount input selectors
$(document).ready(function() {
const commonSelectors = [
'#id_amount',
'#id_charge_amount',
'input[name="amount"]',
'input[name="unit_price"]',
'input[name="price"]'
];
initNumberFormatting(commonSelectors);
// Make helper functions globally available for AJAX forms
window.formatNumber = formatNumber;
window.unformatNumber = unformatNumber;
window.getRawValue = getRawValue;
// Avoid name collision causing recursion by aliasing helpers
const __nf_setRawValuesForSubmission = setRawValuesForSubmission;
const __nf_restoreFormattedValues = restoreFormattedValues;
window.setRawValuesForSubmission = function() { __nf_setRawValuesForSubmission(commonSelectors); };
window.restoreFormattedValues = function() { __nf_restoreFormattedValues(commonSelectors); };
});