diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 53b57f5..0000000 --- a/.travis.yml +++ /dev/null @@ -1,51 +0,0 @@ -dist: bionic -language: groovy -jdk: -- openjdk11 -sudo: false -addons: - chrome: stable -branches: - only: - - master - - dev - - /^feature\/.*$/ - - /^hotfix\/.*$/ - - grails3 - - devg3 - - grails4 - - grails4-bs-branch - - grails5 - -before_cache: - - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ -cache: - directories: - - $HOME/.m2 - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ - -before_install: -- export TZ=Australia/Canberra -- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - -before_script: -- export DETECT_CHROMEDRIVER_VERSION=true -- cd $TRAVIS_BUILD_DIR -- npm install -- npm run-script package-turf -script: -- cd $TRAVIS_BUILD_DIR -#- ./gradlew -PenableClover=true cloverGenerateReport -- node_modules/karma/bin/karma start karma.conf.js --single-run --browsers ChromeHeadless - -# need to gradlew clean before publishing to rebuild without the clover instrumentation. -after_success: - - '[ "${TRAVIS_PULL_REQUEST}" = "false" ] && travis_retry ./gradlew clean && ./gradlew publish' - -env: - global: - - TRAVIS_NODE_VERSION="15.4.0" - - secure: APIxsQqe4M4rIPwU1wKwq6DabQ+CrFu2onzp9k8R9Bv0InewxUf0eOWsp8Xl2m3/Lh7IgUkxI5GbuBvZm/j3NRCkA+VuHBSbA1qUu9aDkUQrtyHzkoe+Uk9Ze0QO22O7//WtbtH/bqgvbagCUk1W5sL6h2aL081td760DY+h+D43XvegqFTSE2mWLvZDD7gz3Lw982LLn7DwQhVOAws+h3fXhydRtqSU+ig6SAr1lzhVyrRLFLAqh1V3canZXh1RKZ28aRwEYUxnVi4kVvH254ogx++bL81pmMfatcebsXUCuAfc6FS1m/QGz6wyqdKO0mZIsAavWmtoKBEbzwNMBS0fZVuW9rslRdJd+K+vQOhigTaWyqj7MlfdY7o99y+trcQECvPGDlw0eYThpeRZK1h1r1auOuSZ46FiXRsWtiSQ3f6GQSRERXiKczvlSqZlNWiWswcNtOS60QvMDdRKa2RRLPrtgPNuG/BnHdaH197riTa74jOW3pgjRZTJyT5aRkHTdZS4l1B/JWjZBwY9yjukfwtFql4HHf8o7jtbTUSXqWt80fwlxXQBEcXxKJzn1vpnEpydS/GeftDFOCXfEFZpM+z6ben3Ti5PufjYfX1Emb6ZwEb/IDhYeCK/xTZlvqxbDgepLqeMiuV+CeHo0NBcu3qnORQMiTZCdEs1hFU= - - secure: ufGvrU/vc0XQ8dbcx9ER4eb8MQloeVvC8ToQrwh3T5WUN4CbnugJ2EcSqoGAsXSZ2VUqE8NmdN2VfCQ6KxAtWKvNNxoe1M33DMgS1hRLWOa934Z7+cZ9RlclW29WGi9C4zpPMd4rJdeGyQMr+q4+TZWuk/I48DXRKyWv3FM4t68F52Jlr0wagWPr1oFJScjzJmmAPReJivF8g49d24rE9G2x04PYy/yCOmgiqUuYhArYKmqdquQL2X/SF4ifFpFIADKw9K6Ari48JskwXweuDCzrvHnj7xeDkDt9uiIpe85nf+th9MmS5NOX4nIod8y6NJyTdflD/k1vVRSLILtu21PXXnn7SpuLpS3FuSh4tKjEO3wZrndFiVqMobv7DaYkxshldRMkNHqeyZUThl2H4hskk2BkK/DaHwPg/JDdlyk8MmaN7LJEezmGhIEtZiEm62NVKU5vGDUB2UmyFEhI4UjcIrfyGR77P5xTW4iBHagP10qqMNrNZ8CkaugfuefI9PCK+nt7YuvP1s+AV05TKNrO7QFFw7+6k5Stv+kJb/k6Vfs4hUCM0Uhv01oYr3dZa9s+Sra/BS2mkmdurNcp0s4AZg4HbXcd03dCfA7dF5EVS2pObVViWy8CDUREc2XMWYKxdwals17Q8O7SjSHHzngXX7Jj0lw1EKQQtgoyb6g= diff --git a/grails-app/assets/javascripts/knockout-utils.js b/grails-app/assets/javascripts/knockout-utils.js index 7e09a50..d4f9397 100644 --- a/grails-app/assets/javascripts/knockout-utils.js +++ b/grails-app/assets/javascripts/knockout-utils.js @@ -164,7 +164,22 @@ * @param precision the number of decimal places allowed. * @returns {Computed} */ - ko.extenders.numericString = function(target, precision) { + ko.extenders.numericString = function(target, options) { + var defaults = { + decimalPlaces: 2, + removeTrailingZeros: true // backwards compatibility + }; + if (_.isNumber(options)) { + options = {decimalPlaces: options}; + } + options = _.extend({}, defaults, options); + + function roundAndToString(value) { + var roundingMultiplier = Math.pow(10, options.decimalPlaces); + var roundedValue = Math.round(value * roundingMultiplier) / roundingMultiplier; + return roundedValue.toString(); + } + //create a writable computed observable to intercept writes to our observable var result = ko.computed({ read: target, //always return the original observables value @@ -173,18 +188,18 @@ if (typeof val === 'string') { val = newValue.replace(/,|\$/g, ''); } - var current = target(), - roundingMultiplier = Math.pow(10, precision), - newValueAsNum = isNaN(val) ? 0 : parseFloat(+val), - valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier; + var current = target(); + var newValueAsNum = isNaN(val) ? 0 : parseFloat(+val); + + var valueToWrite = options.removeTrailingZeros ? roundAndToString(newValueAsNum) : newValueAsNum.toFixed(options.decimalPlaces); //only write if it changed - if (valueToWrite.toString() !== current || isNaN(val)) { - target(isNaN(val) ? newValue : valueToWrite.toString()); + if (valueToWrite !== current || isNaN(val)) { + target(isNaN(val) ? newValue : valueToWrite); } else { if (newValue !== current) { - target.notifySubscribers(valueToWrite.toString()); + target.notifySubscribers(valueToWrite); } } } diff --git a/grails-app/taglib/au/org/ala/ecodata/forms/ModelJSTagLib.groovy b/grails-app/taglib/au/org/ala/ecodata/forms/ModelJSTagLib.groovy index b186dde..52ea12a 100644 --- a/grails-app/taglib/au/org/ala/ecodata/forms/ModelJSTagLib.groovy +++ b/grails-app/taglib/au/org/ala/ecodata/forms/ModelJSTagLib.groovy @@ -624,7 +624,11 @@ class ModelJSTagLib { def numberViewModel(JSModelRenderContext ctx) { int decimalPlaces = ctx.dataModel.decimalPlaces ?: 2 - observable(ctx, ["{numericString:${decimalPlaces}}"]) + + Map options = new HashMap(ctx.viewModel()?.displayOptions ?: [:]) + options.decimalPlaces = decimalPlaces + String optionString = (options as JSON).toString() + observable(ctx, ["{numericString:${optionString}}"]) } def dateViewModel(JSModelRenderContext ctx) { diff --git a/src/test/groovy/au/org/ala/ecodata/forms/ModelJSTagLibSpec.groovy b/src/test/groovy/au/org/ala/ecodata/forms/ModelJSTagLibSpec.groovy index 4eb3c19..948f175 100644 --- a/src/test/groovy/au/org/ala/ecodata/forms/ModelJSTagLibSpec.groovy +++ b/src/test/groovy/au/org/ala/ecodata/forms/ModelJSTagLibSpec.groovy @@ -44,7 +44,7 @@ class ModelJSTagLibSpec extends Specification implements TagLibUnitTest