Skip to content

Commit

Permalink
proposed fix for jdorn#388 using math.js
Browse files Browse the repository at this point in the history
Make math.js an optional dependency. Also add support for decimal.js
  • Loading branch information
Adam Bloomston authored and jdorn committed Feb 11, 2016
1 parent cfd3419 commit ac4728b
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 41 deletions.
24 changes: 12 additions & 12 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,25 @@ module.exports = function(grunt) {
sourcesContent: true
},
target: {
files: {
files: {
'dist/jsoneditor.js': [

// License & version info, start the containing closure
'src/intro.js',

// Simple inheritance
'src/class.js',
// IE9 polyfills
'src/ie9.js',
// Utils like extend, each, and trigger
'src/utilities.js',

// The main JSONEditor class
'src/core.js',

// JSON Schema validator
'src/validator.js',

// All the editors
'src/editor.js',
'src/editors/null.js',
Expand Down Expand Up @@ -54,10 +54,10 @@ module.exports = function(grunt) {

// Set the defaults
'src/defaults.js',

// Wrapper for $.fn style initialization
'src/jquery.js',

// End the closure
'src/outro.js'
],
Expand Down Expand Up @@ -91,20 +91,20 @@ module.exports = function(grunt) {
beforeconcat: [
'src/class.js',
'src/ie9.js',

// Utils like extend, each, and trigger
'src/utilities.js',

// The main JSONEditor class
'src/core.js',

// JSON Schema validator
'src/validator.js',

// All the editors
'src/editor.js',
'src/editors/*.js',

// All the themes and iconlibs
'src/theme.js',
'src/themes/*.js',
Expand All @@ -116,7 +116,7 @@ module.exports = function(grunt) {

// Set the defaults
'src/defaults.js',

// Wrapper for $.fn style initialization
'src/jquery.js'
],
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ Download the [production version][min] (22K when gzipped) or the [development ve
Requirements
-----------------

JSON Editor has no required dependencies. It only needs a modern browser (tested in Chrome and Firefox).
JSON Schema has the following dependencies:

* [math.js](http://mathjs.org/) for floating point math

It needs a modern browser (tested in Chrome and Firefox).

### Optional Requirements

Expand Down
74 changes: 54 additions & 20 deletions src/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,48 +208,82 @@ JSONEditor.Validator = Class.extend({
if(typeof value === "number") {
// `multipleOf` and `divisibleBy`
if(schema.multipleOf || schema.divisibleBy) {
valid = value / (schema.multipleOf || schema.divisibleBy);
if(valid !== Math.floor(valid)) {
var divisor = schema.multipleOf || schema.divisibleBy;
// Vanilla JS, prone to floating point rounding errors (e.g. 1.14 / .01 == 113.99999)
valid = (value/divisor === Math.floor(value/divisor));

// Use math.js is available
if(window.math) {
valid = window.math.mod(window.math.bignumber(value), window.math.bignumber(divisor)).equals(0);
}
// Use decimal.js is available
else if(window.Decimal) {
valid = (new window.Decimal(value)).mod(new window.Decimal(divisor)).equals(0);
}

if(!valid) {
errors.push({
path: path,
property: schema.multipleOf? 'multipleOf' : 'divisibleBy',
message: this.translate('error_multipleOf', [schema.multipleOf || schema.divisibleBy])
message: this.translate('error_multipleOf', [divisor])
});
}
}

// `maximum`
if(schema.hasOwnProperty('maximum')) {
if(schema.exclusiveMaximum && value >= schema.maximum) {
errors.push({
path: path,
property: 'maximum',
message: this.translate('error_maximum_excl', [schema.maximum])
});
// Vanilla JS, prone to floating point rounding errors (e.g. .999999999999999 == 1)
valid = schema.exclusiveMaximum? (value < schema.maximum) : (value <= schema.maximum);

// Use math.js is available
if(window.math) {
valid = window.math[schema.exclusiveMaximum?'smaller':'smallerEq'](
window.math.bignumber(value),
window.math.bignumber(schema.maximum)
);
}
// Use Decimal.js if available
else if(window.Decimal) {
valid = (new window.Decimal(value))[schema.exclusiveMaximum?'lt':'lte'](new window.Decimal(schema.maximum));
}
else if(!schema.exclusiveMaximum && value > schema.maximum) {

if(!valid) {
errors.push({
path: path,
property: 'maximum',
message: this.translate('error_maximum_incl', [schema.maximum])
message: this.translate(
(schema.exclusiveMaximum?'error_maximum_excl':'error_maximum_incl'),
[schema.maximum]
)
});
}
}

// `minimum`
if(schema.hasOwnProperty('minimum')) {
if(schema.exclusiveMinimum && value <= schema.minimum) {
errors.push({
path: path,
property: 'minimum',
message: this.translate('error_minimum_excl', [schema.minimum])
});
// Vanilla JS, prone to floating point rounding errors (e.g. .999999999999999 == 1)
valid = schema.exclusiveMinimum? (value > schema.minimum) : (value >= schema.minimum);

// Use math.js is available
if(window.math) {
valid = window.math[schema.exclusiveMinimum?'larger':'largerEq'](
window.math.bignumber(value),
window.math.bignumber(schema.minimum)
);
}
// Use Decimal.js if available
else if(window.Decimal) {
valid = (new window.Decimal(value))[schema.exclusiveMinimum?'gt':'gte'](new window.Decimal(schema.minimum));
}
else if(!schema.exclusiveMinimum && value < schema.minimum) {

if(!valid) {
errors.push({
path: path,
property: 'minimum',
message: this.translate('error_minimum_incl', [schema.minimum])
message: this.translate(
(schema.exclusiveMinimum?'error_minimum_excl':'error_minimum_incl'),
[schema.minimum]
)
});
}
}
Expand All @@ -269,7 +303,7 @@ JSONEditor.Validator = Class.extend({

// `minLength`
if(schema.minLength) {
if((value+"").length < schema.minLength) {
if((value+"").length < schema.minLength) {
errors.push({
path: path,
property: 'minLength',
Expand Down
24 changes: 16 additions & 8 deletions tests/validation.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<title>JSON Editor Validation Example</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src='../dist/jsoneditor.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/mathjs/2.7.0/math.min.js'></script>
</head>
<body>
<div id='output'></div>
Expand Down Expand Up @@ -217,6 +218,13 @@
valid: [5,0,10],
invalid: [5.5,8,1]
},
multipleOfDecimal: {
schema: {
multipleOf: .01
},
valid: [1,1.14,3.57,56],
invalid: [1.012]
},
minmax: {
schema: {
type: "object",
Expand Down Expand Up @@ -530,7 +538,7 @@
schema: "",
schema2: 2
}
]
]
},
definitions: {
schema: {
Expand All @@ -545,7 +553,7 @@
},
definitions: {
diskDevice: {
pattern: "^/dev/[^/]+(/[^/]+)*$"
pattern: "^/dev/[^/]+(/[^/]+)*$"
},
external: {
"$ref": "http://localhost/json-editor/tests/string.json"
Expand Down Expand Up @@ -667,7 +675,7 @@
}
]
},

disallow: {
schema: {
type: "object",
Expand All @@ -677,7 +685,7 @@
"string",
{
type: "number",
maximum: 5
maximum: 5
}
]
},
Expand Down Expand Up @@ -717,7 +725,7 @@
invalid: ["1999","abc","abc 1999-01-01","1999-01-01 abc"]
}
};

// Custom validators must return an array of errors or an empty array if valid
$.jsoneditor.custom_validators.push(function(schema, value, path) {
var errors = [];
Expand All @@ -733,13 +741,13 @@
}
return errors;
});

var num = 0;
var animel = $("<div></div>");
$.each(tests,function(i,test) {
animel.queue(function(next) {
console.log(i);

try {
var editor = new JSONEditor(document.createElement('div'),{
schema: test.schema,
Expand All @@ -750,7 +758,7 @@
console.log(test.schema);
throw e;
}

editor.on('ready',function() {
$.each(test.valid,function(j,value) {
try {
Expand Down

0 comments on commit ac4728b

Please sign in to comment.