///#source 1 1 /ClientSource/Scripts/Modules/jQuery-NumberFormatter/jshashtable-2.1.js /** * Copyright 2010 Tim Down. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var Hashtable=(function(){var p="function";var n=(typeof Array.prototype.splice==p)?function(s,r){s.splice(r,1)}:function(u,t){var s,v,r;if(t===u.length-1){u.length=t}else{s=u.slice(t+1);u.length=t;for(v=0,r=s.length;v "ae" * Australia -> "au" * Austria -> "at" * Brazil -> "br" * Canada -> "ca" * China -> "cn" * Czech -> "cz" * Denmark -> "dk" * Egypt -> "eg" * Finland -> "fi" * France -> "fr" * Germany -> "de" * Greece -> "gr" * Great Britain -> "gb" * Hong Kong -> "hk" * India -> "in" * Israel -> "il" * Japan -> "jp" * Russia -> "ru" * South Korea -> "kr" * Spain -> "es" * Sweden -> "se" * Switzerland -> "ch" * Taiwan -> "tw" * Thailand -> "th" * United States -> "us" * Vietnam -> "vn" **/ (function(jQuery) { var nfLocales = new Hashtable(); var nfLocalesLikeUS = [ 'ae','au','ca','cn','eg','gb','hk','il','in','jp','sk','th','tw','us' ]; var nfLocalesLikeDE = [ 'at','br','de','dk','es','gr','it','nl','pt','tr','vn' ]; var nfLocalesLikeFR = [ 'cz','fi','fr','ru','se','pl' ]; var nfLocalesLikeCH = [ 'ch' ]; var nfLocaleFormatting = [ [".", ","], [",", "."], [",", " "], [".", "'"] ]; var nfAllLocales = [ nfLocalesLikeUS, nfLocalesLikeDE, nfLocalesLikeFR, nfLocalesLikeCH ] function FormatData(dec, group, neg) { this.dec = dec; this.group = group; this.neg = neg; }; function init() { // write the arrays into the hashtable for (var localeGroupIdx = 0; localeGroupIdx < nfAllLocales.length; localeGroupIdx++) { localeGroup = nfAllLocales[localeGroupIdx]; for (var i = 0; i < localeGroup.length; i++) { nfLocales.put(localeGroup[i], localeGroupIdx); } } }; function formatCodes(locale, isFullLocale) { if (nfLocales.size() == 0) init(); // default values var dec = "."; var group = ","; var neg = "-"; if (isFullLocale == false) { // Extract and convert to lower-case any language code from a real 'locale' formatted string, if not use as-is // (To prevent locale format like : "fr_FR", "en_US", "de_DE", "fr_FR", "en-US", "de-DE") if (locale.indexOf('_') != -1) locale = locale.split('_')[1].toLowerCase(); else if (locale.indexOf('-') != -1) locale = locale.split('-')[1].toLowerCase(); } // hashtable lookup to match locale with codes var codesIndex = nfLocales.get(locale); if (codesIndex) { var codes = nfLocaleFormatting[codesIndex]; if (codes) { dec = codes[0]; group = codes[1]; } } return new FormatData(dec, group, neg); }; /* Formatting Methods */ /** * Formats anything containing a number in standard js number notation. * * @param {Object} options The formatting options to use * @param {Boolean} writeBack (true) If the output value should be written back to the subject * @param {Boolean} giveReturnValue (true) If the function should return the output string */ jQuery.fn.formatNumber = function(options, writeBack, giveReturnValue) { return this.each(function() { // enforce defaults if (writeBack == null) writeBack = true; if (giveReturnValue == null) giveReturnValue = true; // get text var text; if (jQuery(this).is(":input")) text = new String(jQuery(this).val()); else text = new String(jQuery(this).text()); // format var returnString = jQuery.formatNumber(text, options); // set formatted string back, only if a success // if (returnString) { if (writeBack) { if (jQuery(this).is(":input")) jQuery(this).val(returnString); else jQuery(this).text(returnString); } if (giveReturnValue) return returnString; // } // return ''; }); }; /** * First parses a string and reformats it with the given options. * * @param {Object} numberString * @param {Object} options */ jQuery.formatNumber = function(numberString, options){ var options = jQuery.extend({}, jQuery.fn.formatNumber.defaults, options); var formatData = formatCodes(options.locale.toLowerCase(), options.isFullLocale); var dec = formatData.dec; var group = formatData.group; var neg = formatData.neg; var validFormat = "0#-,."; // strip all the invalid characters at the beginning and the end // of the format, and we'll stick them back on at the end // make a special case for the negative sign "-" though, so // we can have formats like -$23.32 var prefix = ""; var negativeInFront = false; for (var i = 0; i < options.format.length; i++) { if (validFormat.indexOf(options.format.charAt(i)) == -1) prefix = prefix + options.format.charAt(i); else if (i == 0 && options.format.charAt(i) == '-') { negativeInFront = true; continue; } else break; } var suffix = ""; for (var i = options.format.length - 1; i >= 0; i--) { if (validFormat.indexOf(options.format.charAt(i)) == -1) suffix = options.format.charAt(i) + suffix; else break; } options.format = options.format.substring(prefix.length); options.format = options.format.substring(0, options.format.length - suffix.length); // now we need to convert it into a number //while (numberString.indexOf(group) > -1) // numberString = numberString.replace(group, ''); //var number = new Number(numberString.replace(dec, ".").replace(neg, "-")); var number = new Number(numberString); return jQuery._formatNumber(number, options, suffix, prefix, negativeInFront); }; /** * Formats a Number object into a string, using the given formatting options * * @param {Object} numberString * @param {Object} options */ jQuery._formatNumber = function(number, options, suffix, prefix, negativeInFront) { var options = jQuery.extend({}, jQuery.fn.formatNumber.defaults, options); var formatData = formatCodes(options.locale.toLowerCase(), options.isFullLocale); var dec = formatData.dec; var group = formatData.group; var neg = formatData.neg; var forcedToZero = false; if (isNaN(number)) { if (options.nanForceZero == true) { number = 0; forcedToZero = true; } else return null; } // special case for percentages if (suffix == "%") number = number * 100; var returnString = ""; if (options.format.indexOf(".") > -1) { var decimalPortion = dec; var decimalFormat = options.format.substring(options.format.lastIndexOf(".") + 1); // round or truncate number as needed if (options.round == true) number = new Number(number.toFixed(decimalFormat.length)); else { var numStr = number.toString(); numStr = numStr.substring(0, numStr.lastIndexOf('.') + decimalFormat.length + 1); number = new Number(numStr); } var decimalValue = number % 1; var decimalString = new String(decimalValue.toFixed(decimalFormat.length)); decimalString = decimalString.substring(decimalString.lastIndexOf(".") + 1); for (var i = 0; i < decimalFormat.length; i++) { if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) != '0') { decimalPortion += decimalString.charAt(i); continue; } else if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) == '0') { var notParsed = decimalString.substring(i); if (notParsed.match('[1-9]')) { decimalPortion += decimalString.charAt(i); continue; } else break; } else if (decimalFormat.charAt(i) == "0") decimalPortion += decimalString.charAt(i); } returnString += decimalPortion } else number = Math.round(number); var ones = Math.floor(number); if (number < 0) ones = Math.ceil(number); var onesFormat = ""; if (options.format.indexOf(".") == -1) onesFormat = options.format; else onesFormat = options.format.substring(0, options.format.indexOf(".")); var onePortion = ""; if (!(ones == 0 && onesFormat.substr(onesFormat.length - 1) == '#') || forcedToZero) { // find how many digits are in the group var oneText = new String(Math.abs(ones)); var groupLength = 9999; if (onesFormat.lastIndexOf(",") != -1) groupLength = onesFormat.length - onesFormat.lastIndexOf(",") - 1; var groupCount = 0; for (var i = oneText.length - 1; i > -1; i--) { onePortion = oneText.charAt(i) + onePortion; groupCount++; if (groupCount == groupLength && i != 0) { onePortion = group + onePortion; groupCount = 0; } } // account for any pre-data padding if (onesFormat.length > onePortion.length) { var padStart = onesFormat.indexOf('0'); if (padStart != -1) { var padLen = onesFormat.length - padStart; // pad to left with 0's or group char var pos = onesFormat.length - onePortion.length - 1; while (onePortion.length < padLen) { var padChar = onesFormat.charAt(pos); // replace with real group char if needed if (padChar == ',') padChar = group; onePortion = padChar + onePortion; pos--; } } } } if (!onePortion && onesFormat.indexOf('0', onesFormat.length - 1) !== -1) onePortion = '0'; returnString = onePortion + returnString; // handle special case where negative is in front of the invalid characters if (number < 0 && negativeInFront && prefix.length > 0) prefix = neg + prefix; else if (number < 0) returnString = neg + returnString; if (!options.decimalSeparatorAlwaysShown) { if (returnString.lastIndexOf(dec) == returnString.length - 1) { returnString = returnString.substring(0, returnString.length - 1); } } returnString = prefix + returnString + suffix; return returnString; }; /* Parsing Methods */ /** * Parses a number of given format from the element and returns a Number object. * @param {Object} options */ jQuery.fn.parseNumber = function(options, writeBack, giveReturnValue) { // enforce defaults if (writeBack == null) writeBack = true; if (giveReturnValue == null) giveReturnValue = true; // get text var text; if (jQuery(this).is(":input")) text = new String(jQuery(this).val()); else text = new String(jQuery(this).text()); // parse text var number = jQuery.parseNumber(text, options); if (number) { if (writeBack) { if (jQuery(this).is(":input")) jQuery(this).val(number.toString()); else jQuery(this).text(number.toString()); } if (giveReturnValue) return number; } }; /** * Parses a string of given format into a Number object. * * @param {Object} string * @param {Object} options */ jQuery.parseNumber = function(numberString, options) { var options = jQuery.extend({}, jQuery.fn.parseNumber.defaults, options); var formatData = formatCodes(options.locale.toLowerCase(), options.isFullLocale); var dec = formatData.dec; var group = formatData.group; var neg = formatData.neg; var valid = "1234567890.-"; // now we need to convert it into a number while (numberString.indexOf(group)>-1) numberString = numberString.replace(group,''); numberString = numberString.replace(dec,".").replace(neg,"-"); var validText = ""; var hasPercent = false; if (numberString.charAt(numberString.length - 1) == "%" || options.isPercentage == true) hasPercent = true; for (var i=0; i-1) validText = validText + numberString.charAt(i); } var number = new Number(validText); if (hasPercent) { number = number / 100; var decimalPos = validText.indexOf('.'); if (decimalPos != -1) { var decimalPoints = validText.length - decimalPos - 1; number = number.toFixed(decimalPoints + 2); } else { number = number.toFixed(validText.length - 1); } } return number; }; jQuery.fn.parseNumber.defaults = { locale: "us", decimalSeparatorAlwaysShown: false, isPercentage: false, isFullLocale: false }; jQuery.fn.formatNumber.defaults = { format: "#,###.00", locale: "us", decimalSeparatorAlwaysShown: false, nanForceZero: true, round: true, isFullLocale: false }; Number.prototype.toFixed = function(precision) { return jQuery._roundNumber(this, precision); }; jQuery._roundNumber = function(number, decimalPlaces) { var power = Math.pow(10, decimalPlaces || 0); var value = String(Math.round(number * power) / power); // ensure the decimal places are there if (decimalPlaces > 0) { var dp = value.indexOf("."); if (dp == -1) { value += '.'; dp = 0; } else { dp = value.length - (dp + 1); } while (dp < decimalPlaces) { value += '0'; dp++; } } return value; }; })(jQuery);