jwidget

Core jWidget utilities. Some utilities duplicate the functions of Underscore.js and Lodash, but still may come in handy if you want to keep dependency list short.

Consumption

import * as jwidget from "jwidget";

Enumerations#

Binding#

Binding: enum

jWidget binding modes. All options have shorthands, i.e. Binding.UPDATE can be imported separately as {UPDATE}.

UPDATE = 1

Bind element attribute to property.

    // Bind element value to property
    bindVal(el, property, UPDATE);

Always used as default binding. Hence, the next code is almost equivalent:

    bindVal(el, property);

Please prefer the second approach, because the first one takes IProperty as an argument whereas Bindable is enough for the second one.

WATCH = 2

Bind property to element attribute.

    // Bind property to element value
    bindVal(el, property, WATCH);

Always supplied with a no-argument method, which creates the property automatically.

    // Watch element value
    const property = bindVal(el);
TWOWAY = 3

Bind element attribute and property to each other.

UPDATE-binding is applied first, WATCH is applied last.

    // Assign element value to property and setup two-way binding
    bindVal(el, property, TWOWAY);

CollectionFlags#

CollectionFlags: enum

jWidget collection flags. All options have shorthands, i.e. CollectionFlags.SILENT can be imported separately as {SILENT}.

SILENT = 1

Creates a silent collection, which means that it never triggers modification events. Silent collections work a little bit faster and consume less memory. Useful for collections that never get modified or observed.

    const silentList = new List<number>([1, 2], SILENT);
    const mappedList = mapList(silentList, (value) => 2 * value);
    expect(mappedList.items).toEqual([2, 4]);
    silentList.add(3);
    expect(mappedList.items).toEqual([2, 4]); // 6 is not added, because source list is silent
ADAPTER = 2

Creates an adapter for an existing array or dictionary, which means that it uses the same object as a container for the collection contents instead of creating a new container. Note that you should not modify the original array or dictionary in this case, because it may break the collection consistency.

    const originalArray = [1, 2];
    const adapterList = new List<number>(originalArray, ADAPTER);
    adapterList.add(3);
    expect(originalArray).toEqual([1, 2, 3]); // 3 is added to original array, because the list is adapter

Pass both flags via bitwise disjunction operator:

new List<number>(originalArray, SILENT | ADAPTER);

Value test functions#

These functions are useful for collection filtering:

const realValues = values.filter(isNotNil);

Which is a shorter equivalent for:

const readValues = values.filter((value) => value != null);

isUndefined#

(value: any): boolean

value
Value to test.
returns
Value is undefined.

isDefined#

(value: any): boolean

value
Value to test.
returns
Value is not undefined.

isNull#

(value: any): boolean

value
Value to test.
returns
Value is null.

isNotNull#

(value: any): boolean

value
Value to test.
returns
Value is not null.

isNil#

(value: any): boolean

value
Value to test.
returns
Value is undefined or null.

isNotNil#

(value: any): boolean

value
Value to test.
returns
Value is not undefined and null.

isFalsy#

(value: any): boolean

value
Value to test.
returns
Value is falsy (i.e. Boolean(value) is false).

isTruthy#

(value: any): boolean

value
Value to test.
returns
Value is truthy (i.e. Boolean(value) is true).

isInt#

(value: any): boolean

value
Value to test.
returns
Value is integer.

isNumber#

(value: any): boolean

value
Value to test.
returns
Value is number.

isString#

(value: any): boolean

value
Value to test.
returns
Value is string.

isBoolean#

(value: any): boolean

value
Value to test.
returns
Value is boolean.

isFunction#

(value: any): boolean

value
Value to test.
returns
Value is function.

isArray#

(value: any): boolean

value
Value to test.
returns
Value is native JavaScript Array.

isRegExp#

(value: any): boolean

value
Value to test.
returns
Value is regular expression.

isDate#

(value: any): boolean

value
Value to test.
returns
Value is date.

Other functions#

def#

<T>(value: T, defaultValue: T): T

value
Value to test.
defaultValue
Default value to return.
returns
value if it is not undefined, else defaultValue.
As opposed to defn, treats null as suitable value.

defn#

<T>(value: T, defaultValue: T): T

value
Value to test.
defaultValue
Default value to return.
returns
value if it is not undefined and null, else defaultValue.
As opposed to def, throws null as unsuitable value.

apply#

<T>(target: Dictionary<T>, ...sources: Dictionary<T>[]): Dictionary<T>

target
Target dictionary to copy the values to.
sources
Source dictionaries.
returns
target

Iterates through objects passed after first argument and copies all their fields into target object. Returns target. Undefined source values are ignored. Null and undefined source dictionaries are ignored.

Function modifies target object!

var x: Dictionary<number> = { |  var y: Dictionary<number> = {  // Result = {
    a: 10,                    |                                 //     a: 10,
    b: 20,                    |      b: 30,                     //     b: 30,
    c: null,                  |      c: 40,                     //     c: 40,
    d: undefined,             |      d: 50,                     //     d: 50,
    e: null                   |                                 //     e: null,
                              |      f: 60,                     //     f: 60
                              |      g: undefined               //
};                            |  };                             // };

apply<number>(x, y);

cmp#

(x: any, y: any, config?: CmpConfig): number

x
First value to compare.
y
Second value to compare.
config
Optional configuration.
returns
One or {-1, 0, 1} as comparison result.

Universal and sophisticated comparer for array sorting. Broadly speaking, it:

  • Returns 1, if x > y
  • Returns -1, if x < y
  • Returns 0, if x == y

In reality, it supports the next features:

  • Comparing of boolean, number, string, Identifiable (by iid) values, subarrays
  • Determined linear order, even for mixed arrays
  • Case insensitive comparing for strings
  • Comparing of digit sequences in strings as numbers
Example

Sort by color descending first, and by status ascending last. Both parameters are optional.

rows.sort((x, y) => {
    return cmp(x.color == null, y.color == null) ||
          -cmp(x.color, y.color) ||
           cmp(x.status == null, y.status == null) ||
           cmp(x.status, y.status);
});

CmpConfig#

Optional configuration of cmp function.
caseInsensitive#

readonly caseInsensitive: boolean = false

Ignore case when comparing strings.
compareNumbersInStrings#

readonly compareNumbersInStrings: boolean = false

Compare digit sequences as numbers when comparing strings.

get#

<T>(obj: any, path: any): T

obj
Object to inspect.
path
Field name or path to it.
returns
Field value.

Returns object field or subfield by path. Path is a primitive value (object key), or an array of subpaths. If path is null, undefined or empty array, returns obj. If item doesn't exist, returns undefined.

Example
const obj = {
    abc: [
        {
            qwe: "xyz"
        }
    ]
};

expect(get(obj, ["abc", 0, "qwe"])).toBe("xyz");
expect(get(obj, "abc")).toBe(obj.abc);

newIid#

(): number

returns
New unique auto-incremented integer identified.

Returns a new auto-incremented instance identifier for Identifiable interface. Class constructor calls it automatically.

iidStr#

(obj: Identifiable): string

obj
Object to inspect.
returns
iid field of obj converted to a string.

Can be used as efficient getKey implementation for collections consisting of Identifiable objects only. Since default getKey implementation analyzes input value nature very deeply, it has performance penalty. Specifying iidStr for collections of Identifiable objects may improve performance significantly.

destroy#

(obj: any): any

obj
Object to destroy.
returns
undefined.

Calls destroy method of obj if available. Can be used in configuration of any mapper.

const views = mapList(models, (model) => new View(model), {destroy});

Doesn't return anything - any return type is specified for easier usage in methods like ArrayUtils.backEvery.