Help making a standalone maths operator to format thousands

Folks,

As a Java Script Kiddy. I need some assistance from someone with Javascript in tiddlywiki skills.

I have a working filter operator called thousands. I am not sure where I obtained the JS code to do this but I added it to $:/core/modules/filters/math.js and it works well $__core_modules_filters_math.js.json (7.0 KB)

  • eg {{{ [[1000345.3]thousands[]] }}} produces 1,000,345.3.

However I would like to turn this into a standalone filter operator module, rather than overwrite the core modual.

I placed the following in its own tiddler but it is not working. I believe it needs access to other functions found in $:/core/modules/filters/math.js

exports. Thousands = makeNumericBinaryOperator(
    function(a) {
        // Splitting the number into integer and fractional parts
        var parts = a.toString().split(".");
        // Formatting the integer part with commas
        parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
        // Concatenating the integer and fractional parts back together
        return parts. Join(".");
    }
);

Further I am aware that other “languages” use the opposite to us in Australia, So wonder how to parameterise this or obtain these from localisation.

  • eg {{{ [[1000345.3]thousands[]] }}} would produce 1.000.345,3.

Some assistance would be appreciated.

The thousand marker is language specific. See: Intl.NumberFormat - JavaScript | MDN

You should have a look at filter operator, that only contains 1 operator. It will show the whole construction needed to make it work. eg: contains.js

But I think it should be an element of the filter operator and it should have some the options that are described in the link. So eg:

  • [[12345.6]format:currency[de-DE],[EUR]] or
  • [[12345.6]format:number[de-DE]] or

something like this. I am not sure without testing it.

1 Like

That is nice simple code, using a sophisticated regular expression!

That’s right. It depends upon a helper function used across the math module but not exposed externally, makeNumericBinaryOperator. There is an interesting question of whether such helpers should be made public; they are designed for use within math, but as you demonstrate, they could well be used by others.

One way to get around this issue would be to simply repeat such helper functions in your module. Once you have it working as you like, nothing would break when the core function changes. But it feels rather slimy.

A second alternative is to simply skip the helper function and build it directly. By combining that helper function and your code, we can write what’s still a relatively simple module1:

exports.thousands = function(source, operator, options) {
	var result = [];
	source(function(tiddler,title) {
		var parts = title.toString().split(".");
		parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
		result.push(parts.join('.'));
	});
	return result;
};

You can see that here (you’ll have to reload after import, because it’s a JS module):

thousands.json (1.1 KB)

But I think that in the end, this would be better done as @pmario suggests as an extension to the format operator, and should use the NumberFormat API in some way.

Let me know if you want explanations of how the code works.




1 We can add options to replace the symbols used (, and .) with others (such as . and ,) like this:

exports.thousands = function(source, operator, options) {
	var result = [],
		thousandsSep = (operator.operands && operator.operands[0]) || ",",
		decimalSep = (operator.operands && operator.operands[1]) || ".";
	source(function(tiddler,title) {
		var parts = title.toString().split(".");
		parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSep);
		result.push(parts.join(decimalSep));
	});
	return result;
};

We would then call it like this:

  • [[1650763.73]thousands[]]: "1,650,763.73"
  • [[1650763.73]thousands[.][,]]: "1.650.763,73"
2 Likes