From 73608d31bd8f58315c8628a03f9b084731d956cd Mon Sep 17 00:00:00 2001 From: Sverchkov Nikolay Date: Wed, 2 Aug 2017 17:09:58 +0300 Subject: [PATCH 1/3] try to update formatCurrency library --- .../spree/backend/spree_flexi_variants.js | 2 +- .../spree/frontend/spree_flexi_variants.js | 2 +- .../jquery.formatCurrency-1.4.0.min.js | 25 -- .../javascripts/jquery.formatCurrency.min.js | 406 ++++++++++++++++++ 4 files changed, 408 insertions(+), 27 deletions(-) delete mode 100644 vendor/assets/javascripts/jquery.formatCurrency-1.4.0.min.js create mode 100644 vendor/assets/javascripts/jquery.formatCurrency.min.js diff --git a/app/assets/javascripts/spree/backend/spree_flexi_variants.js b/app/assets/javascripts/spree/backend/spree_flexi_variants.js index 2762f06..af3f721 100644 --- a/app/assets/javascripts/spree/backend/spree_flexi_variants.js +++ b/app/assets/javascripts/spree/backend/spree_flexi_variants.js @@ -1,4 +1,4 @@ -//= require jquery.formatCurrency-1.4.0.min +//= require jquery.formatCurrency.min //= require i18n/jquery.formatCurrency.all //= require jquery.validate/jquery.validate.min //= require_tree diff --git a/app/assets/javascripts/spree/frontend/spree_flexi_variants.js b/app/assets/javascripts/spree/frontend/spree_flexi_variants.js index 51817c5..152f8ce 100644 --- a/app/assets/javascripts/spree/frontend/spree_flexi_variants.js +++ b/app/assets/javascripts/spree/frontend/spree_flexi_variants.js @@ -1,4 +1,4 @@ -//= require jquery.formatCurrency-1.4.0.min +//= require jquery.formatCurrency.min //= require i18n/jquery.formatCurrency.all //= require_self diff --git a/vendor/assets/javascripts/jquery.formatCurrency-1.4.0.min.js b/vendor/assets/javascripts/jquery.formatCurrency-1.4.0.min.js deleted file mode 100644 index d26c4a9..0000000 --- a/vendor/assets/javascripts/jquery.formatCurrency-1.4.0.min.js +++ /dev/null @@ -1,25 +0,0 @@ -(function($){$.formatCurrency={};$.formatCurrency.regions=[];$.formatCurrency.regions[""]={symbol:"$",positiveFormat:"%s%n",negativeFormat:"(%s%n)",decimalSymbol:".",digitGroupSymbol:",",groupDigits:true}; -$.fn.formatCurrency=function(destination,settings){if(arguments.length==1&&typeof destination!=="string"){settings=destination;destination=false -}var defaults={name:"formatCurrency",colorize:false,region:"",global:true,roundToDecimalPlace:2,eventOnDecimalsEntered:false};defaults=$.extend(defaults,$.formatCurrency.regions[""]); -settings=$.extend(defaults,settings);if(settings.region.length>0){settings=$.extend(settings,getRegionOrCulture(settings.region))}settings.regex=generateRegex(settings); -return this.each(function(){$this=$(this);var num="0";num=$this[$this.is("input, select, textarea")?"val":"html"]();if(num.search("\\(")>=0){num="-"+num -}if(num===""||(num==="-"&&settings.roundToDecimalPlace===-1)){return}if(isNaN(num)){num=num.replace(settings.regex,"");if(num===""||(num==="-"&&settings.roundToDecimalPlace===-1)){return -}if(settings.decimalSymbol!="."){num=num.replace(settings.decimalSymbol,".")}if(isNaN(num)){num="0"}}var numParts=String(num).split(".");var isPositive=(num==Math.abs(num)); -var hasDecimals=(numParts.length>1);var decimals=(hasDecimals?numParts[1].toString():"0");var originalDecimals=decimals;num=Math.abs(numParts[0]); -num=isNaN(num)?0:num;if(settings.roundToDecimalPlace>=0){decimals=parseFloat("1."+decimals);decimals=decimals.toFixed(settings.roundToDecimalPlace); -if(decimals.substring(0,1)=="2"){num=Number(num)+1}decimals=decimals.substring(2)}num=String(num);if(settings.groupDigits){for(var i=0;i0){num+=settings.decimalSymbol+decimals -}var format=isPositive?settings.positiveFormat:settings.negativeFormat;var money=format.replace(/%s/g,settings.symbol);money=money.replace(/%n/g,num); -var $destination=$([]);if(!destination){$destination=$this}else{$destination=$(destination)}$destination[$destination.is("input, select, textarea")?"val":"html"](money); -if(hasDecimals&&settings.eventOnDecimalsEntered&&originalDecimals.length>settings.roundToDecimalPlace){$destination.trigger("decimalsEntered",originalDecimals) -}if(settings.colorize){$destination.css("color",isPositive?"black":"red")}})};$.fn.toNumber=function(settings){var defaults=$.extend({name:"toNumber",region:"",global:true},$.formatCurrency.regions[""]); -settings=jQuery.extend(defaults,settings);if(settings.region.length>0){settings=$.extend(settings,getRegionOrCulture(settings.region))}settings.regex=generateRegex(settings); -return this.each(function(){var method=$(this).is("input, select, textarea")?"val":"html";$(this)[method]($(this)[method]().replace("(","(-").replace(settings.regex,"")) -})};$.fn.asNumber=function(settings){var defaults=$.extend({name:"asNumber",region:"",parse:true,parseType:"Float",global:true},$.formatCurrency.regions[""]); -settings=jQuery.extend(defaults,settings);if(settings.region.length>0){settings=$.extend(settings,getRegionOrCulture(settings.region))}settings.regex=generateRegex(settings); -settings.parseType=validateParseType(settings.parseType);var method=$(this).is("input, select, textarea")?"val":"html";var num=$(this)[method](); -num=num?num:"";num=num.replace("(","(-");num=num.replace(settings.regex,"");if(!settings.parse){return num}if(num.length==0){num="0"}if(settings.decimalSymbol!="."){num=num.replace(settings.decimalSymbol,".") -}return window["parse"+settings.parseType](num)};function getRegionOrCulture(region){var regionInfo=$.formatCurrency.regions[region];if(regionInfo){return regionInfo -}else{if(/(\w+)-(\w+)/g.test(region)){var culture=region.replace(/(\w+)-(\w+)/g,"$1");return $.formatCurrency.regions[culture]}}return null}function validateParseType(parseType){switch(parseType.toLowerCase()){case"int":return"Int"; -case"float":return"Float";default:throw"invalid parseType"}}function generateRegex(settings){if(settings.symbol===""){return new RegExp("[^\\d"+settings.decimalSymbol+"-]","g") -}else{var symbol=settings.symbol.replace("$","\\$").replace(".","\\.");return new RegExp(symbol+"|[^\\d"+settings.decimalSymbol+"-]","g")}}})(jQuery); \ No newline at end of file diff --git a/vendor/assets/javascripts/jquery.formatCurrency.min.js b/vendor/assets/javascripts/jquery.formatCurrency.min.js new file mode 100644 index 0000000..005abf4 --- /dev/null +++ b/vendor/assets/javascripts/jquery.formatCurrency.min.js @@ -0,0 +1,406 @@ +// This file is part of the jQuery formatCurrency Plugin. +// +// The jQuery formatCurrency Plugin is free software: you can redistribute it +// and/or modify it under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The jQuery formatCurrency Plugin is distributed in the hope that it will +// be useful, but WITHOUT ANY WARRANTY; without even the implied warranty +// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License along with +// the jQuery formatCurrency Plugin. If not, see . + +;(function ($) { + $.formatCurrency = {}; + $.formatCurrencyLive = {}; + $.toNumber = {}; + $.asNumber = {}; + + var fcDefaults = { + colorize: false, + region: '', + roundToDecimalPlace: 2, // roundToDecimalPlace: -2; for not allowing decimals; roundToDecimalPlace: -1; for no rounding; 0 to round to the dollar; 1 for one digit cents; 2 for two digit cents; 3 for three digit cents; ... + minimumDecimalPlaces: 9, + eventOnDecimalsEntered: false, + suppressCurrencySymbol: false, + removeTrailingZerosOnDecimal: false, + parseAsFloat: false + }; + + var fcLiveDefaults = { + decPointCharCodes: [], // by index: 0 - key code for key press event; 1 & 2 key codes for keyup event for the decimal point keys on the keyboard and keypad, respectively + formatOnBlur: true, + filterKeys: true, + formatOnType: true + }; + + var toNumberDefaults = { + region: '' + }; + + var asNumberDefaults = { + region: '', + parse: true, + parseType: 'Float' + }; + + $.formatCurrency.regions = []; + + // default Region is en + $.formatCurrency.regions[''] = { + symbol: '$', + positiveFormat: '%s%n', + negativeFormat: '(%s%n)', + decimalSymbol: '.', + digitGroupSymbol: ',', + groupDigits: true + }; + + $.formatCurrencyLive.setDefaults = function(settings) { + $.extend(fcLiveDefaults, settings); + }; + + $.fn.formatCurrencyLive = function (settings) { + return this.each(function () { + var $this = $(this); + + settings = buildSettingsObjGraph( + settings, + $.extend( + {}, + fcDefaults, + fcLiveDefaults, + ($this.data('formatCurrency') ? $this.data('formatCurrency') : {}) + ) + ); + + // setup the decimal point charCode setting according to the region + if (settings.roundToDecimalPlace === -2) + settings.decPointCharCodes = [-1, -1, -1]; + else { + if (settings.decimalSymbol == ',') + settings.decPointCharCodes = [44, 188, 110]; + else + settings.decPointCharCodes = [46, 190, 110]; + } + + $this.data('formatCurrency', settings); + + if (settings.filterKeys) + $this.off('keypress.formatCurrency') + .on('keypress.formatCurrency', function (ev) { + if (!keyAllowed(ev, settings.decPointCharCodes)) ev.preventDefault(); + }); + + if (settings.formatOnType) { + var settingsFmtOnType = $.extend({}, settings, { roundToDecimalPlace: -1, removeTrailingZerosOnDecimal: false }); + $this.off('keyup.formatCurrency') + .on('keyup.formatCurrency', function (ev) { + if (keyAllowed(ev, settings.decPointCharCodes)) $(this).formatCurrency(settingsFmtOnType); + }); + } + + if (settings.formatOnBlur) + $this.on('blur.formatCurrency', function (ev) { + $(this).formatCurrency(settings); + }); + + $(this).formatCurrency(settings); + }); + }; + + $.formatCurrency.setDefaults = function(settings) { + $.extend(fcDefaults, settings); + }; + + $.formatCurrency.setAllDefaults = function(settings) { + for (var prop in settings) { + if(fcDefaults.hasOwnProperty(prop)) fcDefaults[prop] = settings[prop]; + if(fcLiveDefaults.hasOwnProperty(prop)) fcLiveDefaults[prop] = settings[prop]; + if(toNumberDefaults.hasOwnProperty(prop)) toNumberDefaults[prop] = settings[prop]; + if(asNumberDefaults.hasOwnProperty(prop)) asNumberDefaults[prop] = settings[prop]; + } + }; + + $.fn.formatCurrency = function (destination, settings) { + + if (arguments.length == 1 && typeof destination !== "string") { + settings = destination; + destination = false; + } + + // if this element has settings associated with it by the live Formatter and no settings + // was specified, use the stored settings. Else, build the settings object as normal + settings = ($(this).data('formatCurrency') && !settings ? + $(this).data('formatCurrency') : + settings + ); + + return this.each(function () { + var $this = $(this); + + // get number + var num = '0'; + num = $this[$this.is('input, select, textarea') ? 'val' : 'html'](); + + var money = $.getFormattedCurrency(num, settings, true); + settings = money[4]; + + $this.data('fcMetadata', { + 'hasDecimals': money[1], + 'originalDecimals': money[2], + 'isPositive': money[3] + }); + + if(!money) return; + + // setup destination + var $destination = $([]); + if (!destination) { + $destination = $this; + } else { + $destination = $(destination); + } + // set destination + $destination[$destination.is('input, select, textarea') ? 'val' : 'html'](money[0]); + + if (money[1] && + settings.eventOnDecimalsEntered && + money[2].length > 0) { + $destination.trigger('decimalsEntered', money[2]); + } + + // colorize + if (settings.colorize) $destination.css('color', money[3] ? 'black' : 'red'); + }); + }; + + $.getFormattedCurrency = function (expr, settings, returnMetadata) { + settings = buildSettingsObjGraph(settings, fcDefaults); + + if (settings.parseAsFloat) { + var tryFloat = parseFloat(expr); + expr = isNaN(tryFloat) ? expr : tryFloat; + } + + expr = (typeof(expr) !== "string" ? expr.toString().replace('\.', settings.decimalSymbol) : expr); + + //identify '(123)' as a negative number + if (expr.search('\\(') >= 0) + expr = '-' + expr; + + if (expr === '' || (expr === '-' && settings.roundToDecimalPlace === -1)) + return (returnMetadata ? [ expr, false, "", true, settings ] : ""); + + expr = expr.replace(settings.symbol, ''); // Remove currency symbol for arithmetic + expr = expr.replace(settings.regexGroupDigit, ''); // Remove group digit for arithmetic + + if (settings.decimalSymbol != '.') + expr = expr.replace(settings.decimalSymbol, '.'); // reset to US decimal for arithmetic + + // if the number is valid use it, otherwise clean it + if (isNaN(expr)) { + // clean number + expr = expr.replace(settings.regexArithmetic, ''); + + if (expr === '' || (expr === '-' && settings.roundToDecimalPlace === -1)) + expr = '0'; + + if (isNaN(expr)) + expr = '0'; + } + + var isPositive = (expr == Math.abs(expr)); + if (!isPositive && settings.disableNegative === true) { + expr = 0; + isPositive = true; + } + + // evalutate number input + var numParts = String(expr).split('.'); + var hasDecimals = (numParts.length > 1 && settings.roundToDecimalPlace > -2); + var decimals = (hasDecimals ? numParts[1].toString() : '0'); + var originalDecimals = hasDecimals || decimals != '0' ? decimals : ''; + + // format number + expr = Math.abs(numParts[0]); + expr = isNaN(expr) ? 0 : expr; + if (settings.roundToDecimalPlace >= 0) { + decimals = parseFloat('1.' + decimals); // prepend "0."; (IE does NOT round 0.50.toFixed(0) up, but (1+0.50).toFixed(0)-1 + decimals = decimals.toFixed(settings.roundToDecimalPlace); // round + if (decimals.substring(0, 1) == '2') { + expr = Number(expr) + 1; + } + decimals = decimals.substring(2); // remove "0." + } + expr = String(expr); + + if (settings.groupDigits) { + for (var i = 0; i < Math.floor((expr.length - (1 + i)) / 3); i++) { + expr = expr.substring(0, expr.length - (4 * i + 3)) + settings.digitGroupSymbol + expr.substring(expr.length - (4 * i + 3)); + } + } + + if ((hasDecimals && settings.roundToDecimalPlace == -1) || settings.roundToDecimalPlace > 0) { + if (settings.removeTrailingZerosOnDecimal) { + decimals = decimals.replace(/0+$/, ''); + if (decimals.length < settings.minimumDecimalPlaces) decimals = String(decimals + Array(settings.minimumDecimalPlaces+1).join('0')).slice(0,settings.minimumDecimalPlaces); + } + expr += (decimals.length > 0 ? settings.decimalSymbol + decimals : ""); + } + + // format symbol/negative + var format = isPositive ? settings.positiveFormat : settings.negativeFormat; + var money = format; + money = money.replace(/%s/g, settings.symbol); + money = money.replace(/%n/g, expr); + + return (returnMetadata ? [ money, hasDecimals, originalDecimals, isPositive, settings ] : money); + }; + + // Remove all non numbers from text + $.toNumber.setDefaults = function(settings) { + $.extend(toNumberDefaults, settings); + }; + + $.fn.toNumber = function (settings) { + return this.each(function () { + var method = $(this).is('input, select, textarea') ? 'val' : 'html'; + $(this)[method]($.toNumber($(this)[method](), settings)); + }); + }; + + $.toNumber = function(expr, settings) { + settings = buildSettingsObjGraph(settings, toNumberDefaults); + + return expr.replace('(', '(-').replace(settings.regex, ''); + }; + + // returns the value from the first element as a number + $.asNumber.setDefaults = function(settings) { + $.extend(asNumberDefaults, settings); + }; + + $.fn.asNumber = function (settings) { + var method = $(this).is('input, select, textarea') ? 'val' : 'html'; + var num = $(this)[method](); + + return $.asNumber(num, settings) + }; + + $.asNumber = function(expr, settings) { + settings = buildSettingsObjGraph(settings, asNumberDefaults); + + expr = expr ? expr : ""; + expr = expr.replace('(', '(-'); + expr = expr.replace(settings.regex, ''); + if (!settings.parse) return expr; + + if (expr.length == 0) expr = '0'; + + if (settings.decimalSymbol != '.') expr = expr.replace(settings.decimalSymbol, '.'); // reset to US decimal for arithmetic + + return window['parse' + settings.parseType](expr); + }; + + function buildSettingsObjGraph(settings, defaults) { + if (!settings) settings = {}; + var bareSettings = settings; + + // build settings graph starting from the defaults and merging region settings if needed + settings = $.extend( + {}, + defaults, + $.formatCurrency.regions[''], + settings + ); + + if (settings.region !== '') $.extend(settings, getRegionOrCulture(settings.region), bareSettings); + + if (settings.suppressCurrencySymbol) { + settings.symbol = ''; + settings.positiveFormat = $.trim(settings.positiveFormat.replace('%s', '')); + settings.negativeFormat = $.trim(settings.negativeFormat.replace('%s', '').replace(' %n', '%n')); + } + + if (settings.roundToDecimalPlace >= -1) { + settings.minimumDecimalPlaces = (settings.roundToDecimalPlace == -1 || settings.minimumDecimalPlaces > settings.roundToDecimalPlace ? settings.roundToDecimalPlace : settings.minimumDecimalPlaces); + } else { + settings.minimumDecimalPlaces = 0; + } + + // validate parseType if it exists (for the 'asNumber' settings object graph) + if (settings.hasOwnProperty('parseType')) + settings.parseType = validateParseType(settings.parseType); + + // Generate regex for formatting + settings.regexArithmetic = new RegExp("[^\\d\\.\\-]", "g"); + if (settings.symbol === '') + settings.regex = new RegExp("[^\\d" + settings.decimalSymbol + "-]", "g"); + else { + var symbol = settings.symbol.replace('$', '\\$').replace('.', '\\.'); + settings.regex = new RegExp(symbol + "|[^\\d" + settings.decimalSymbol + "-]", "g"); + } + + settings.regexGroupDigit = new RegExp("\\" + settings.digitGroupSymbol, "g"); + + return settings; + } + + function keyAllowed(ev, decPointCodes) { + if (ev.which >= 48 && ev.which <= 57) + return true; + else if (ev.type == 'keypress' && ev.which == decPointCodes[0]) + return (ev.target.value.indexOf(String.fromCharCode(decPointCodes[0])) == -1); + else if (ev.type == 'keypress') { + if (ev.ctrlKey && ev.key.toUpperCase() == "A") return true; + return (ev.which < 32 || (ev.which >= 33 && ev.which <= 40) || (decPointCodes[0] != -1 && ev.which == 46)); + } else if (ev.type == 'keyup') { + if (ev.ctrlKey && ev.key.toUpperCase() == "A") return false; + + if(ev.which < 32 || (ev.which >= 33 && ev.which <= 40)) return false; + + if(decPointCodes[0] != -1) { + switch (ev.which) { + case 78: break; // N (Opera 9.63+ maps the "." from the number key section to the "N" key too!) (See: http://unixpapa.com/js/key.html search for ". Del") + case decPointCodes[2]: break; // . number block (Opera 9.63+ maps the "." from the number block to the "N" key (78) !!!) + case decPointCodes[1]: break; // . + default: return true; + } + } + + return false; + } else + return true; + } + + function getRegionOrCulture(region) { + var regionInfo = $.formatCurrency.regions[region]; + if (regionInfo) { + return regionInfo; + } + else { + if (/(\w+)-(\w+)/g.test(region)) { + var culture = region.replace(/(\w+)-(\w+)/g, "$1"); + return $.formatCurrency.regions[culture]; + } + } + // fallback to extend(null) (i.e. nothing) + return null; + } + + function validateParseType(parseType) { + switch (parseType.toLowerCase()) { + case 'int': + return 'Int'; + case 'float': + return 'Float'; + default: + throw 'invalid parseType'; + } + } + +})(jQuery); From 6c955838973dbdf5bf3d4671d1ef6d8f3e931f4b Mon Sep 17 00:00:00 2001 From: Sverchkov Nikolay Date: Wed, 2 Aug 2017 18:42:02 +0300 Subject: [PATCH 2/3] added currency format options --- app/views/spree/products/_pricing.html.erb | 4 +++- lib/spree/flexi_variants_configuration.rb | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/views/spree/products/_pricing.html.erb b/app/views/spree/products/_pricing.html.erb index b9ebf8e..6c9102f 100644 --- a/app/views/spree/products/_pricing.html.erb +++ b/app/views/spree/products/_pricing.html.erb @@ -123,7 +123,9 @@ var cur_price = base_price + cur_variant_price_diff + cur_configuration_price + cur_customization_price; var region = $.formatCurrency.getRegionFromCurrency("<%= @product.currency %>"); - $('.price.selling').text(cur_price.toFixed(2)).formatCurrency({region: region}); + var defaultOptions = <%= raw SpreeFlexiVariants::Config[:format_currency_options].to_json %> + var formatOptions = Object.assign({region: region}, defaultOptions) + $('.price.selling').text(cur_price.toFixed(2)).formatCurrency(formatOptions); } //]]> diff --git a/lib/spree/flexi_variants_configuration.rb b/lib/spree/flexi_variants_configuration.rb index 6c7da45..9d9664b 100644 --- a/lib/spree/flexi_variants_configuration.rb +++ b/lib/spree/flexi_variants_configuration.rb @@ -1,4 +1,5 @@ class Spree::FlexiVariantsConfiguration < Spree::Preferences::Configuration preference :use_javascript_pricing_updates, :boolean, default: true preference :use_separate_customizations_page, :boolean, default: false + preference :format_currency_options, :hash, default: {} end From c89b717e03d0009b8db3c9ad999213dce4da99e9 Mon Sep 17 00:00:00 2001 From: Sverchkov Nikolay Date: Wed, 2 Aug 2017 18:46:52 +0300 Subject: [PATCH 3/3] minify js --- .../javascripts/jquery.formatCurrency.min.js | 444 ++---------------- 1 file changed, 38 insertions(+), 406 deletions(-) diff --git a/vendor/assets/javascripts/jquery.formatCurrency.min.js b/vendor/assets/javascripts/jquery.formatCurrency.min.js index 005abf4..e3c25e0 100644 --- a/vendor/assets/javascripts/jquery.formatCurrency.min.js +++ b/vendor/assets/javascripts/jquery.formatCurrency.min.js @@ -1,406 +1,38 @@ -// This file is part of the jQuery formatCurrency Plugin. -// -// The jQuery formatCurrency Plugin is free software: you can redistribute it -// and/or modify it under the terms of the GNU Lesser General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// The jQuery formatCurrency Plugin is distributed in the hope that it will -// be useful, but WITHOUT ANY WARRANTY; without even the implied warranty -// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License along with -// the jQuery formatCurrency Plugin. If not, see . - -;(function ($) { - $.formatCurrency = {}; - $.formatCurrencyLive = {}; - $.toNumber = {}; - $.asNumber = {}; - - var fcDefaults = { - colorize: false, - region: '', - roundToDecimalPlace: 2, // roundToDecimalPlace: -2; for not allowing decimals; roundToDecimalPlace: -1; for no rounding; 0 to round to the dollar; 1 for one digit cents; 2 for two digit cents; 3 for three digit cents; ... - minimumDecimalPlaces: 9, - eventOnDecimalsEntered: false, - suppressCurrencySymbol: false, - removeTrailingZerosOnDecimal: false, - parseAsFloat: false - }; - - var fcLiveDefaults = { - decPointCharCodes: [], // by index: 0 - key code for key press event; 1 & 2 key codes for keyup event for the decimal point keys on the keyboard and keypad, respectively - formatOnBlur: true, - filterKeys: true, - formatOnType: true - }; - - var toNumberDefaults = { - region: '' - }; - - var asNumberDefaults = { - region: '', - parse: true, - parseType: 'Float' - }; - - $.formatCurrency.regions = []; - - // default Region is en - $.formatCurrency.regions[''] = { - symbol: '$', - positiveFormat: '%s%n', - negativeFormat: '(%s%n)', - decimalSymbol: '.', - digitGroupSymbol: ',', - groupDigits: true - }; - - $.formatCurrencyLive.setDefaults = function(settings) { - $.extend(fcLiveDefaults, settings); - }; - - $.fn.formatCurrencyLive = function (settings) { - return this.each(function () { - var $this = $(this); - - settings = buildSettingsObjGraph( - settings, - $.extend( - {}, - fcDefaults, - fcLiveDefaults, - ($this.data('formatCurrency') ? $this.data('formatCurrency') : {}) - ) - ); - - // setup the decimal point charCode setting according to the region - if (settings.roundToDecimalPlace === -2) - settings.decPointCharCodes = [-1, -1, -1]; - else { - if (settings.decimalSymbol == ',') - settings.decPointCharCodes = [44, 188, 110]; - else - settings.decPointCharCodes = [46, 190, 110]; - } - - $this.data('formatCurrency', settings); - - if (settings.filterKeys) - $this.off('keypress.formatCurrency') - .on('keypress.formatCurrency', function (ev) { - if (!keyAllowed(ev, settings.decPointCharCodes)) ev.preventDefault(); - }); - - if (settings.formatOnType) { - var settingsFmtOnType = $.extend({}, settings, { roundToDecimalPlace: -1, removeTrailingZerosOnDecimal: false }); - $this.off('keyup.formatCurrency') - .on('keyup.formatCurrency', function (ev) { - if (keyAllowed(ev, settings.decPointCharCodes)) $(this).formatCurrency(settingsFmtOnType); - }); - } - - if (settings.formatOnBlur) - $this.on('blur.formatCurrency', function (ev) { - $(this).formatCurrency(settings); - }); - - $(this).formatCurrency(settings); - }); - }; - - $.formatCurrency.setDefaults = function(settings) { - $.extend(fcDefaults, settings); - }; - - $.formatCurrency.setAllDefaults = function(settings) { - for (var prop in settings) { - if(fcDefaults.hasOwnProperty(prop)) fcDefaults[prop] = settings[prop]; - if(fcLiveDefaults.hasOwnProperty(prop)) fcLiveDefaults[prop] = settings[prop]; - if(toNumberDefaults.hasOwnProperty(prop)) toNumberDefaults[prop] = settings[prop]; - if(asNumberDefaults.hasOwnProperty(prop)) asNumberDefaults[prop] = settings[prop]; - } - }; - - $.fn.formatCurrency = function (destination, settings) { - - if (arguments.length == 1 && typeof destination !== "string") { - settings = destination; - destination = false; - } - - // if this element has settings associated with it by the live Formatter and no settings - // was specified, use the stored settings. Else, build the settings object as normal - settings = ($(this).data('formatCurrency') && !settings ? - $(this).data('formatCurrency') : - settings - ); - - return this.each(function () { - var $this = $(this); - - // get number - var num = '0'; - num = $this[$this.is('input, select, textarea') ? 'val' : 'html'](); - - var money = $.getFormattedCurrency(num, settings, true); - settings = money[4]; - - $this.data('fcMetadata', { - 'hasDecimals': money[1], - 'originalDecimals': money[2], - 'isPositive': money[3] - }); - - if(!money) return; - - // setup destination - var $destination = $([]); - if (!destination) { - $destination = $this; - } else { - $destination = $(destination); - } - // set destination - $destination[$destination.is('input, select, textarea') ? 'val' : 'html'](money[0]); - - if (money[1] && - settings.eventOnDecimalsEntered && - money[2].length > 0) { - $destination.trigger('decimalsEntered', money[2]); - } - - // colorize - if (settings.colorize) $destination.css('color', money[3] ? 'black' : 'red'); - }); - }; - - $.getFormattedCurrency = function (expr, settings, returnMetadata) { - settings = buildSettingsObjGraph(settings, fcDefaults); - - if (settings.parseAsFloat) { - var tryFloat = parseFloat(expr); - expr = isNaN(tryFloat) ? expr : tryFloat; - } - - expr = (typeof(expr) !== "string" ? expr.toString().replace('\.', settings.decimalSymbol) : expr); - - //identify '(123)' as a negative number - if (expr.search('\\(') >= 0) - expr = '-' + expr; - - if (expr === '' || (expr === '-' && settings.roundToDecimalPlace === -1)) - return (returnMetadata ? [ expr, false, "", true, settings ] : ""); - - expr = expr.replace(settings.symbol, ''); // Remove currency symbol for arithmetic - expr = expr.replace(settings.regexGroupDigit, ''); // Remove group digit for arithmetic - - if (settings.decimalSymbol != '.') - expr = expr.replace(settings.decimalSymbol, '.'); // reset to US decimal for arithmetic - - // if the number is valid use it, otherwise clean it - if (isNaN(expr)) { - // clean number - expr = expr.replace(settings.regexArithmetic, ''); - - if (expr === '' || (expr === '-' && settings.roundToDecimalPlace === -1)) - expr = '0'; - - if (isNaN(expr)) - expr = '0'; - } - - var isPositive = (expr == Math.abs(expr)); - if (!isPositive && settings.disableNegative === true) { - expr = 0; - isPositive = true; - } - - // evalutate number input - var numParts = String(expr).split('.'); - var hasDecimals = (numParts.length > 1 && settings.roundToDecimalPlace > -2); - var decimals = (hasDecimals ? numParts[1].toString() : '0'); - var originalDecimals = hasDecimals || decimals != '0' ? decimals : ''; - - // format number - expr = Math.abs(numParts[0]); - expr = isNaN(expr) ? 0 : expr; - if (settings.roundToDecimalPlace >= 0) { - decimals = parseFloat('1.' + decimals); // prepend "0."; (IE does NOT round 0.50.toFixed(0) up, but (1+0.50).toFixed(0)-1 - decimals = decimals.toFixed(settings.roundToDecimalPlace); // round - if (decimals.substring(0, 1) == '2') { - expr = Number(expr) + 1; - } - decimals = decimals.substring(2); // remove "0." - } - expr = String(expr); - - if (settings.groupDigits) { - for (var i = 0; i < Math.floor((expr.length - (1 + i)) / 3); i++) { - expr = expr.substring(0, expr.length - (4 * i + 3)) + settings.digitGroupSymbol + expr.substring(expr.length - (4 * i + 3)); - } - } - - if ((hasDecimals && settings.roundToDecimalPlace == -1) || settings.roundToDecimalPlace > 0) { - if (settings.removeTrailingZerosOnDecimal) { - decimals = decimals.replace(/0+$/, ''); - if (decimals.length < settings.minimumDecimalPlaces) decimals = String(decimals + Array(settings.minimumDecimalPlaces+1).join('0')).slice(0,settings.minimumDecimalPlaces); - } - expr += (decimals.length > 0 ? settings.decimalSymbol + decimals : ""); - } - - // format symbol/negative - var format = isPositive ? settings.positiveFormat : settings.negativeFormat; - var money = format; - money = money.replace(/%s/g, settings.symbol); - money = money.replace(/%n/g, expr); - - return (returnMetadata ? [ money, hasDecimals, originalDecimals, isPositive, settings ] : money); - }; - - // Remove all non numbers from text - $.toNumber.setDefaults = function(settings) { - $.extend(toNumberDefaults, settings); - }; - - $.fn.toNumber = function (settings) { - return this.each(function () { - var method = $(this).is('input, select, textarea') ? 'val' : 'html'; - $(this)[method]($.toNumber($(this)[method](), settings)); - }); - }; - - $.toNumber = function(expr, settings) { - settings = buildSettingsObjGraph(settings, toNumberDefaults); - - return expr.replace('(', '(-').replace(settings.regex, ''); - }; - - // returns the value from the first element as a number - $.asNumber.setDefaults = function(settings) { - $.extend(asNumberDefaults, settings); - }; - - $.fn.asNumber = function (settings) { - var method = $(this).is('input, select, textarea') ? 'val' : 'html'; - var num = $(this)[method](); - - return $.asNumber(num, settings) - }; - - $.asNumber = function(expr, settings) { - settings = buildSettingsObjGraph(settings, asNumberDefaults); - - expr = expr ? expr : ""; - expr = expr.replace('(', '(-'); - expr = expr.replace(settings.regex, ''); - if (!settings.parse) return expr; - - if (expr.length == 0) expr = '0'; - - if (settings.decimalSymbol != '.') expr = expr.replace(settings.decimalSymbol, '.'); // reset to US decimal for arithmetic - - return window['parse' + settings.parseType](expr); - }; - - function buildSettingsObjGraph(settings, defaults) { - if (!settings) settings = {}; - var bareSettings = settings; - - // build settings graph starting from the defaults and merging region settings if needed - settings = $.extend( - {}, - defaults, - $.formatCurrency.regions[''], - settings - ); - - if (settings.region !== '') $.extend(settings, getRegionOrCulture(settings.region), bareSettings); - - if (settings.suppressCurrencySymbol) { - settings.symbol = ''; - settings.positiveFormat = $.trim(settings.positiveFormat.replace('%s', '')); - settings.negativeFormat = $.trim(settings.negativeFormat.replace('%s', '').replace(' %n', '%n')); - } - - if (settings.roundToDecimalPlace >= -1) { - settings.minimumDecimalPlaces = (settings.roundToDecimalPlace == -1 || settings.minimumDecimalPlaces > settings.roundToDecimalPlace ? settings.roundToDecimalPlace : settings.minimumDecimalPlaces); - } else { - settings.minimumDecimalPlaces = 0; - } - - // validate parseType if it exists (for the 'asNumber' settings object graph) - if (settings.hasOwnProperty('parseType')) - settings.parseType = validateParseType(settings.parseType); - - // Generate regex for formatting - settings.regexArithmetic = new RegExp("[^\\d\\.\\-]", "g"); - if (settings.symbol === '') - settings.regex = new RegExp("[^\\d" + settings.decimalSymbol + "-]", "g"); - else { - var symbol = settings.symbol.replace('$', '\\$').replace('.', '\\.'); - settings.regex = new RegExp(symbol + "|[^\\d" + settings.decimalSymbol + "-]", "g"); - } - - settings.regexGroupDigit = new RegExp("\\" + settings.digitGroupSymbol, "g"); - - return settings; - } - - function keyAllowed(ev, decPointCodes) { - if (ev.which >= 48 && ev.which <= 57) - return true; - else if (ev.type == 'keypress' && ev.which == decPointCodes[0]) - return (ev.target.value.indexOf(String.fromCharCode(decPointCodes[0])) == -1); - else if (ev.type == 'keypress') { - if (ev.ctrlKey && ev.key.toUpperCase() == "A") return true; - return (ev.which < 32 || (ev.which >= 33 && ev.which <= 40) || (decPointCodes[0] != -1 && ev.which == 46)); - } else if (ev.type == 'keyup') { - if (ev.ctrlKey && ev.key.toUpperCase() == "A") return false; - - if(ev.which < 32 || (ev.which >= 33 && ev.which <= 40)) return false; - - if(decPointCodes[0] != -1) { - switch (ev.which) { - case 78: break; // N (Opera 9.63+ maps the "." from the number key section to the "N" key too!) (See: http://unixpapa.com/js/key.html search for ". Del") - case decPointCodes[2]: break; // . number block (Opera 9.63+ maps the "." from the number block to the "N" key (78) !!!) - case decPointCodes[1]: break; // . - default: return true; - } - } - - return false; - } else - return true; - } - - function getRegionOrCulture(region) { - var regionInfo = $.formatCurrency.regions[region]; - if (regionInfo) { - return regionInfo; - } - else { - if (/(\w+)-(\w+)/g.test(region)) { - var culture = region.replace(/(\w+)-(\w+)/g, "$1"); - return $.formatCurrency.regions[culture]; - } - } - // fallback to extend(null) (i.e. nothing) - return null; - } - - function validateParseType(parseType) { - switch (parseType.toLowerCase()) { - case 'int': - return 'Int'; - case 'float': - return 'Float'; - default: - throw 'invalid parseType'; - } - } - -})(jQuery); +;(function($){$.formatCurrency={};$.formatCurrencyLive={};$.toNumber={};$.asNumber={};var fcDefaults={colorize:false,region:'',roundToDecimalPlace:2,minimumDecimalPlaces:9,eventOnDecimalsEntered:false,suppressCurrencySymbol:false,removeTrailingZerosOnDecimal:false,parseAsFloat:false};var fcLiveDefaults={decPointCharCodes:[],formatOnBlur:true,filterKeys:true,formatOnType:true};var toNumberDefaults={region:''};var asNumberDefaults={region:'',parse:true,parseType:'Float'};$.formatCurrency.regions=[];$.formatCurrency.regions['']={symbol:'$',positiveFormat:'%s%n',negativeFormat:'(%s%n)',decimalSymbol:'.',digitGroupSymbol:',',groupDigits:true};$.formatCurrencyLive.setDefaults=function(settings){$.extend(fcLiveDefaults,settings);};$.fn.formatCurrencyLive=function(settings){return this.each(function(){var $this=$(this);settings=buildSettingsObjGraph(settings,$.extend({},fcDefaults,fcLiveDefaults,($this.data('formatCurrency')?$this.data('formatCurrency'):{})));if(settings.roundToDecimalPlace===-2) +settings.decPointCharCodes=[-1,-1,-1];else{if(settings.decimalSymbol==',') +settings.decPointCharCodes=[44,188,110];else +settings.decPointCharCodes=[46,190,110];} +$this.data('formatCurrency',settings);if(settings.filterKeys) +$this.off('keypress.formatCurrency').on('keypress.formatCurrency',function(ev){if(!keyAllowed(ev,settings.decPointCharCodes))ev.preventDefault();});if(settings.formatOnType){var settingsFmtOnType=$.extend({},settings,{roundToDecimalPlace:-1,removeTrailingZerosOnDecimal:false});$this.off('keyup.formatCurrency').on('keyup.formatCurrency',function(ev){if(keyAllowed(ev,settings.decPointCharCodes))$(this).formatCurrency(settingsFmtOnType);});} +if(settings.formatOnBlur) +$this.on('blur.formatCurrency',function(ev){$(this).formatCurrency(settings);});$(this).formatCurrency(settings);});};$.formatCurrency.setDefaults=function(settings){$.extend(fcDefaults,settings);};$.formatCurrency.setAllDefaults=function(settings){for(var prop in settings){if(fcDefaults.hasOwnProperty(prop))fcDefaults[prop]=settings[prop];if(fcLiveDefaults.hasOwnProperty(prop))fcLiveDefaults[prop]=settings[prop];if(toNumberDefaults.hasOwnProperty(prop))toNumberDefaults[prop]=settings[prop];if(asNumberDefaults.hasOwnProperty(prop))asNumberDefaults[prop]=settings[prop];}};$.fn.formatCurrency=function(destination,settings){if(arguments.length==1&&typeof destination!=="string"){settings=destination;destination=false;} +settings=($(this).data('formatCurrency')&&!settings?$(this).data('formatCurrency'):settings);return this.each(function(){var $this=$(this);var num='0';num=$this[$this.is('input, select, textarea')?'val':'html']();var money=$.getFormattedCurrency(num,settings,true);settings=money[4];$this.data('fcMetadata',{'hasDecimals':money[1],'originalDecimals':money[2],'isPositive':money[3]});if(!money)return;var $destination=$([]);if(!destination){$destination=$this;}else{$destination=$(destination);} +$destination[$destination.is('input, select, textarea')?'val':'html'](money[0]);if(money[1]&&settings.eventOnDecimalsEntered&&money[2].length>0){$destination.trigger('decimalsEntered',money[2]);} +if(settings.colorize)$destination.css('color',money[3]?'black':'red');});};$.getFormattedCurrency=function(expr,settings,returnMetadata){settings=buildSettingsObjGraph(settings,fcDefaults);if(settings.parseAsFloat){var tryFloat=parseFloat(expr);expr=isNaN(tryFloat)?expr:tryFloat;} +expr=(typeof(expr)!=="string"?expr.toString().replace('\.',settings.decimalSymbol):expr);if(expr.search('\\(')>=0) +expr='-'+expr;if(expr===''||(expr==='-'&&settings.roundToDecimalPlace===-1)) +return(returnMetadata?[expr,false,"",true,settings]:"");expr=expr.replace(settings.symbol,'');expr=expr.replace(settings.regexGroupDigit,'');if(settings.decimalSymbol!='.') +expr=expr.replace(settings.decimalSymbol,'.');if(isNaN(expr)){expr=expr.replace(settings.regexArithmetic,'');if(expr===''||(expr==='-'&&settings.roundToDecimalPlace===-1)) +expr='0';if(isNaN(expr)) +expr='0';} +var isPositive=(expr==Math.abs(expr));if(!isPositive&&settings.disableNegative===true){expr=0;isPositive=true;} +var numParts=String(expr).split('.');var hasDecimals=(numParts.length>1&&settings.roundToDecimalPlace>-2);var decimals=(hasDecimals?numParts[1].toString():'0');var originalDecimals=hasDecimals||decimals!='0'?decimals:'';expr=Math.abs(numParts[0]);expr=isNaN(expr)?0:expr;if(settings.roundToDecimalPlace>=0){decimals=parseFloat('1.'+decimals);decimals=decimals.toFixed(settings.roundToDecimalPlace);if(decimals.substring(0,1)=='2'){expr=Number(expr)+1;} +decimals=decimals.substring(2);} +expr=String(expr);if(settings.groupDigits){for(var i=0;i0){if(settings.removeTrailingZerosOnDecimal){decimals=decimals.replace(/0+$/,'');if(decimals.length0?settings.decimalSymbol+decimals:"");} +var format=isPositive?settings.positiveFormat:settings.negativeFormat;var money=format;money=money.replace(/%s/g,settings.symbol);money=money.replace(/%n/g,expr);return(returnMetadata?[money,hasDecimals,originalDecimals,isPositive,settings]:money);};$.toNumber.setDefaults=function(settings){$.extend(toNumberDefaults,settings);};$.fn.toNumber=function(settings){return this.each(function(){var method=$(this).is('input, select, textarea')?'val':'html';$(this)[method]($.toNumber($(this)[method](),settings));});};$.toNumber=function(expr,settings){settings=buildSettingsObjGraph(settings,toNumberDefaults);return expr.replace('(','(-').replace(settings.regex,'');};$.asNumber.setDefaults=function(settings){$.extend(asNumberDefaults,settings);};$.fn.asNumber=function(settings){var method=$(this).is('input, select, textarea')?'val':'html';var num=$(this)[method]();return $.asNumber(num,settings)};$.asNumber=function(expr,settings){settings=buildSettingsObjGraph(settings,asNumberDefaults);expr=expr?expr:"";expr=expr.replace('(','(-');expr=expr.replace(settings.regex,'');if(!settings.parse)return expr;if(expr.length==0)expr='0';if(settings.decimalSymbol!='.')expr=expr.replace(settings.decimalSymbol,'.');return window['parse'+settings.parseType](expr);};function buildSettingsObjGraph(settings,defaults){if(!settings)settings={};var bareSettings=settings;settings=$.extend({},defaults,$.formatCurrency.regions[''],settings);if(settings.region!=='')$.extend(settings,getRegionOrCulture(settings.region),bareSettings);if(settings.suppressCurrencySymbol){settings.symbol='';settings.positiveFormat=$.trim(settings.positiveFormat.replace('%s',''));settings.negativeFormat=$.trim(settings.negativeFormat.replace('%s','').replace(' %n','%n'));} +if(settings.roundToDecimalPlace>=-1){settings.minimumDecimalPlaces=(settings.roundToDecimalPlace==-1||settings.minimumDecimalPlaces>settings.roundToDecimalPlace?settings.roundToDecimalPlace:settings.minimumDecimalPlaces);}else{settings.minimumDecimalPlaces=0;} +if(settings.hasOwnProperty('parseType')) +settings.parseType=validateParseType(settings.parseType);settings.regexArithmetic=new RegExp("[^\\d\\.\\-]","g");if(settings.symbol==='') +settings.regex=new RegExp("[^\\d"+settings.decimalSymbol+"-]","g");else{var symbol=settings.symbol.replace('$','\\$').replace('.','\\.');settings.regex=new RegExp(symbol+"|[^\\d"+settings.decimalSymbol+"-]","g");} +settings.regexGroupDigit=new RegExp("\\"+settings.digitGroupSymbol,"g");return settings;} +function keyAllowed(ev,decPointCodes){if(ev.which>=48&&ev.which<=57) +return true;else if(ev.type=='keypress'&&ev.which==decPointCodes[0]) +return(ev.target.value.indexOf(String.fromCharCode(decPointCodes[0]))==-1);else if(ev.type=='keypress'){if(ev.ctrlKey&&ev.key.toUpperCase()=="A")return true;return(ev.which<32||(ev.which>=33&&ev.which<=40)||(decPointCodes[0]!=-1&&ev.which==46));}else if(ev.type=='keyup'){if(ev.ctrlKey&&ev.key.toUpperCase()=="A")return false;if(ev.which<32||(ev.which>=33&&ev.which<=40))return false;if(decPointCodes[0]!=-1){switch(ev.which){case 78:break;case decPointCodes[2]:break;case decPointCodes[1]:break;default:return true;}} +return false;}else +return true;} +function getRegionOrCulture(region){var regionInfo=$.formatCurrency.regions[region];if(regionInfo){return regionInfo;} +else{if(/(\w+)-(\w+)/g.test(region)){var culture=region.replace(/(\w+)-(\w+)/g,"$1");return $.formatCurrency.regions[culture];}} +return null;} +function validateParseType(parseType){switch(parseType.toLowerCase()){case'int':return'Int';case'float':return'Float';default:throw'invalid parseType';}}})(jQuery);