Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions js/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,22 @@ define(['lib/underscore'], function (_) {
// 'Validation_Number_Range_Min',
// 'Validation_Number_Range_Max',
// 'Validation_Number_Range_Between',
// 'Validation_Array_Size_Max',
// 'Validation_Array_Size_Between',
// 'Validation_Array_Items_Invalid',
// 'Validation_Array_Items_Duplicate'
// ];
return {
defaultMessage: _.identity,
decimalPoint: '.',
groupPoint: ',',
groupSize: 3,
numberOfDigits: 2,
percentDecimalDigits: 2,
percentDecimalSeparator: '.',
percentGroupSeparator: '.',
percentGroupSize: 3,
percentPositivePattern: '0',
percentSymbol: '%'
};
});
156 changes: 156 additions & 0 deletions js/humanize/decimal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
define(['component/ko-validation/config'], function (config) {
'use strict';

function getParts(input, decimalChar) {
input = '' + input;
var fracIndex = input.lastIndexOf(decimalChar) + 1;
var parts = {
negative: input.substring(0, 1) == '-' ? '-' : '',
fractional: fracIndex ? input.substr(fracIndex).replace(/\D/g, '') : '',
integral: (fracIndex ? input.substring(0, fracIndex) : input).replace(/\D/g, '')
};
parts.toFloat = function toFloat() {
return parseFloat(parts.negative + '0' + parts.integral + '.' + parts.fractional);
};
return parts;
}

function getFormat() {
return {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_.pick?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ljqx I sign off, and will merge the change, please take care of the node in next iteration.

Thanks
Wei

decimalChar : config.decimalPoint,
groupChar : config.groupPoint,
groupSize : config.groupSize,
percentSymbol : config.percentSymbol,
percentGroupSize : config.percentGroupSize,
percentGroupSeparator : config.percentGroupSeparator,
percentPositivePattern : config.percentPositivePattern,
numberOfDigits : config.numberOfDigits,
percentDecimalDigits : config.percentDecimalDigits,
percentDecimalSeparator : config.percentDecimalSeparator,
};
}

var dn = {
// true/false if exactly formatted correct, no smoothing
isValid: function isValid (localizedInput, allowNoIntegralPart) {
var format = getFormat()
, minGroupSize = 0 // allowNoIntegralPart ? 0 : 1
, re = new RegExp('^[+-]?[0-9]{' + minGroupSize + ',' + format.groupSize + '}(?:\\' + format.groupChar + '?[0-9]{' + format.groupSize + '})*(?:\\' + format.decimalChar + '[[0-9]*)?$')
, isValid = re.test(localizedInput);

return isValid;
},

// returns null if invalid
// rounds if number of digits is passed, otherwise no rounding
fromLocalToFloat: function fromLocalToFloat(localizedInput /*, numberOfDigits */) {
var format = getFormat(),
parts = getParts(localizedInput, format.decimalChar);
// if (parts.fractional || parts.integral) {
var floatValue = parts.toFloat();
// if (numberOfDigits) {
// floatValue = parseFloat(floatValue.toFixed(numberOfDigits));
// }
return floatValue;
// }
// return null;
},

// // returns null if isValid == false
// fromLocalToStringStrict: function (localizedInput, numberOfDigits) {
// if (!dn.isValid(localizedInput))
// {
// return null;
// }

// return dn.fromLocalToString(localizedInput, numberOfDigits);
// },

// // used to validate & format user input
// fromLocalToString: function fromLocalToString(localizedInput, numberOfDigits) {
// var format = getFormat(),
// parts = getParts(localizedInput, format.decimalChar),
// numberOfDigits = typeof numberOfDigits === 'undefined' ? format.numberOfDigits : numberOfDigits,
// cleanedAndRounded = parts.toFloat().toFixed(numberOfDigits).split('.'),
// formattedIntegral = '',
// i = cleanedAndRounded[0].length;

// for (; i > format.groupSize; i -= format.groupSize) {
// formattedIntegral = format.groupChar + cleanedAndRounded[0].substring(i - format.groupSize, i) + formattedIntegral;
// }

// formattedIntegral = cleanedAndRounded[0].substring(0, i) + formattedIntegral;
// if (numberOfDigits) {
// formattedIntegral += format.decimalChar + cleanedAndRounded[1];
// }

// return formattedIntegral;
// },

// // format input to string in percentage format
// fromLocalToPercentString: function fromLocalToString(localizedInput, numberOfDigits) {
// var input = localizedInput * 100;
// var format = getFormat(),
// parts = getParts(input, format.percentDecimalSeparator),
// numberOfDigits = typeof numberOfDigits === 'undefined' ? format.percentDecimalDigits : numberOfDigits,
// cleanedAndRounded = parts.toFloat().toFixed(numberOfDigits).split('.'),
// formattedIntegral = '',
// i = cleanedAndRounded[0].length;

// for (; i > format.percentGroupSize; i -= format.percentGroupSize) {
// formattedIntegral = format.percentGroupSeparator + cleanedAndRounded[0].substring(i - format.percentGroupSize, i) + formattedIntegral;
// }

// formattedIntegral = cleanedAndRounded[0].substring(0, i) + formattedIntegral;
// if (numberOfDigits) {
// formattedIntegral += format.percentDecimalSeparator + cleanedAndRounded[1];
// }

// switch (format.percentPositivePattern) {
// //Associated pattern: n %
// case '0':
// formattedIntegral = formattedIntegral + ' ' + format.percentSymbol;
// break;
// //Associated pattern: n%
// case '1':
// formattedIntegral = formattedIntegral + format.percentSymbol;
// break;
// //Associated pattern: %n
// case '2':
// formattedIntegral = format.percentSymbol + formattedIntegral;
// break;
// //Associated pattern: % n
// case '3':
// formattedIntegral = format.percentSymbol + ' ' + formattedIntegral;
// break;
// }

// return formattedIntegral;
// }
};

// // used to format float values from MT/DB (e.g., always a real number XXX.YY with a period for decimal place
// dn.fromFloatToString = function fromFloatToString(floatInput, numberOfDigits) {
// var format = getFormat();
// return dn.fromLocalToString(floatInput.toString().replace('.', format.decimalChar), numberOfDigits);
// };

// // Used in Location Targeting control to convert Lat/Lon to string using customer culture information
// dn.fromCoordinateToString = function fromCoordinateToString(value) {
// if (value && (typeof decimalFormatter !== 'undefined')) {
// value = value.toString().replace(".", decimalFormatter.decimalChar);
// }

// return value;
// };

// // used to format float value to string with a percent sign. Does NOT convert the float to a percent. Ex: 42.07 => 42.07%, 0.15 => 0.15%
// dn.fromFloatToPercentString = function fromFloatToPercentString(floatInput, numberOfDigits) {
// var format = getFormat();
// //fromLocalToPercentString will multiply the number by 100 and displayed with a percent symbol.
// var input = floatInput / 100;
// return dn.fromLocalToPercentString(input.toString().replace('.', format.decimalChar), numberOfDigits);
// };

return dn;
});
34 changes: 31 additions & 3 deletions js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ define([
'component/ko-validation/validators/string',
'component/ko-validation/validators/number',
'component/ko-validation/validators/enum',
'component/ko-validation/validators/array',
'component/ko-validation/validators/passive',
'component/ko-validation/validators/custom',
'component/ko-validation/ko-extension',
'component/ko-validation/config',
], function (_, Required, String, Number, Enum, Custom, config) {
], function (_, Required, String, Number, Enum, Array, Passive, Custom, config) {
'use strict';

function run(value, validators) {
Expand All @@ -25,8 +27,8 @@ define([
return new String.Type();
}

string.size = function (length) {
return new String.Size(length);
string.size = function (length, blockInput) {
return new String.Size(length, blockInput);
};

string.xss = function () {
Expand All @@ -49,6 +51,30 @@ define([
return new Enum(enumerators, nullable);
}

function array() {
return new Array.Type();
}

array.size = function(min, max) {
return new Array.Size(min, max);
};

array.item = function(validators) {
return new Array.Item(validators);
};

array.items = function(validators, additionalValidators) {
return new Array.Items(validators, additionalValidators);
};

array.unique = function() {
return new Array.Unique();
};

function passive() {
return new Passive();
}

function custom(method, message, blockInput) {
return new Custom(method, message, blockInput);
}
Expand All @@ -59,6 +85,8 @@ define([
string: string,
number: number,
enum: enumeration,
array: array,
passive: passive,
custom: custom,
// end of validators
run: run, // run validation manually, for using without knockout
Expand Down
12 changes: 11 additions & 1 deletion js/ko-extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ define(['lib/knockout', 'lib/underscore'], function (ko, _) {
},
write: function (value) {
observableWrapper.errors.removeAll();
_.each(validators, function(validator) {
if (_.isFunction(validator.process) && !validator.blockInput) {
value = validator.process(value);
}
});

var failedValidations = _.filter(validators, function (v) {
return !v.isValid(value);
});
Expand All @@ -23,7 +29,11 @@ define(['lib/knockout', 'lib/underscore'], function (ko, _) {
return _.isFunction(failed.message) ? failed.message(value) : failed.message;
}));

observable(value);
if (_.isEqual(observable(), value)) {
observable.notifySubscribers();
} else {
observable(value);
}
}
},
}).extend({ notify: 'always' });
Expand Down
Loading