back

Another Way to use Multivalue from Javascript

2022-03-18

I wrote the pick-mv package to help use javascript to manipulate multivalue and I did this by using proxy objects.

https://www.npmjs.com/package/pick-multivalue

This gave me the ability to do stuff like variable[[1,3]]. This is similar to basic and good enough for what I was trying to do. The bonus here was that this way I can also do assignment as well because I could use the set magic method in a proxy.

I needed to port this to wkhtmltopdf which doesn't have any support for proxies and there is no polyfill for it. So I ended up re-writing the pick-mv package and I think I actually like this one more!

Array.prototype.Matrix = function(amPos, vmPos, svmPos) {
    var am = amPos - 1;
    if(!Array.isArray(this)) return am === 0 ? this[am] : '';

    if (am > this.length) return '';

    if (vmPos) {
        var vm = vmPos - 1;
        if(!Array.isArray(this[am])) return vm === 0 ? this[am] : '';
        if (vm > this[am].length) return '';

        if (svmPos) {
            var svm = svmPos-1;
            if(!Array.isArray(this[am][vm])) return svm === 0 ? this[am][vm] : '';
            if (svm > this[am][vm].length) return '';
            return this[am][vm][svm];
        }

        return this[am][vm];

    } else {
        return this[am];
    }
}

It's very similar but the difference is that now its a function call on every array. The way to use it is by doing Order.Matrix(1,2,3). This is actually a much closer syntax to basic which I'm fond of but I can't do assignment here. Luckily for the project I'm going to use this for there is no need for assignment so this is perfect!

Now the line by line explanation so I don't have to constantly re-do the logic :)

The first step is to get the attribute mark position and subtract one. I want to start indexing the way basic does, this way I can keep things somewhat unified.

The next line checks to see if the element is an array and if it isn't then it will check if the attribute mark is 0. If it is the first element that someone's asking for then we can return the entire element. Otherwise return a blank string. Technically this is an array method so by default it will be an array but I'm still trying to figure our if I want to make this a proper function and accept the array as the first parameter.

The next line will check if the am is greater than the length, if it is, then we can just return a blank.

Now before we return the value at that attribute mark we need to check if the person wants to go deeper. We do this by checking to see if the value mark position exists.

If so, now we do the same thing. We subtract one with the assumption we are using indexing starting at 1. Next we check if the value in the attribute is an array. If it isn't, we return the entire attribute if the value mark position is 0. Otherwise we continue.

We then check to see if the value mark being requested is greater than the number of values in the attribute. If it is greater, then we return a blank.

Now before we return the value in the value mark position, we need to check if there are subvalues. If there are subvalues, we'll need to go even deeper.

We do the same thing as before, we change the subvalue position assuming that it is also indexed from 1.

We then check to see if the value being referenced is an array or not. If it isn't an array, we check to see which position is being requested. If the position is 0, we return the value otherwise we return a blank.

Next we check if the subvalue position being requested is inside the range. If it isn't we return a blank.

Finally we can return a subvalue if we did get this far.

Voila! A very simple little snippet that hopefully will help make using multivalue with javascript a little bit easier.

I thought about normalizing everything to return an array as it will make loops easier but I decided it'd be better to maintain consistency with basic. I have a small helped function that checks if something is an array or not and makes it into an array if need be.

function normalize(arr) {
    return [].concat(arr);
}

A very small little function that cleans up a lot of junk code that checks for arrays before running loops.