lib/boilerplate.view.js
function buildViewAttribsSpecial( attName, attValue, code ) {
    const
        type = attValue[ 0 ],
        init = attValue[ 1 ];
    let requireConverter = false;

    try {
        if ( typeof attValue.behind !== 'undefined' ) {
            buildViewAttribsSpecialCodeBehind( attName, attValue.behind, code );
        }
        if ( typeof attValue.debug !== 'undefined' ) {
            buildViewAttribsSpecialDebug( attName, attValue.debug, code );
        }
        if ( Array.isArray( type ) ) {
            // Enumerate.
            code.addCast( "enum" );
            code.section.attribs.define.push(
                "pm.create(" + JSON.stringify( attName ) +
                `, { cast: conv_enum(${JSON.stringify(type)}), init: ${JSON.stringify(init)} });` );
            buildViewAttribsInit( attName, init, code );
        } else {
            switch ( type ) {
            case 'action':
                code.actions.push( attName );
                code.section.attribs.define.push(
                    "pm.createAction(" + JSON.stringify( attName ) + ")" );
                break;
            case 'any':
                code.section.attribs.define.push(
                    "pm.create(" + JSON.stringify( attName ) + ");" );
                buildViewAttribsInit( attName, init, code );
                break;
            case 'boolean':
            case 'booleans':
            case 'date':
            case 'color':
            case 'string':
            case 'strings':
            case 'array':
            case 'list':
            case 'intl':
            case 'time':
            case 'unit':
            case 'units':
            case 'multilang':
            case 'validator':
                requireConverter = true;
                code.vars[ "conv_" + type ] = "Converters.get('" + type + "')";
                code.section.attribs.define.push(
                    "pm.create(" + JSON.stringify( attName ) +
                    ", { cast: conv_" + type + " });" );
                buildViewAttribsInit( attName, init, code );
                break;
            case 'integer':
            case 'float':
                requireConverter = true;
                code.vars[ "conv_" + type ] = "Converters.get('" + type + "')";
                // Is Not a number, take this default value.
                let nanValue = attValue.default;
                if ( typeof nanValue !== 'number' || isNaN( nanValue ) ) {
                    nanValue = 0;
                }
                code.section.attribs.define.push(
                    "pm.create(" + JSON.stringify( attName ) +
                    ", { cast: conv_" + type + "(" + nanValue + ") });" );
                buildViewAttribsInit( attName, init, code );
                break;
            default:
                throw "Unknown type \"" + type + "\" for attribute \"" + attName + "\"!";
            }
        }

        if ( requireConverter ) {
            code.requires.Converters = "require('tfw.binding.converters')";
        }
    } catch ( ex ) {
        bubble(
            ex,
            `buildViewAttribsSpecial(${attName}: ${JSON.stringify(attValue)})`
        );
    }
}
function buildViewAttribsSpecial( attName, attValue, code ) {
    const
        type = attValue[ 0 ],
        init = attValue[ 1 ];
    let requireConverter = false;

    try {
        if ( typeof attValue.behind !== 'undefined' ) {
            buildViewAttribsSpecialCodeBehind( attName, attValue.behind, code );
        }
        if ( typeof attValue.debug !== 'undefined' ) {
            buildViewAttribsSpecialDebug( attName, attValue.debug, code );
        }
        if ( Array.isArray( type ) ) {
            // Enumerate.
            code.addCast( "enum" );
            code.section.attribs.define.push(
                "pm.create(" + JSON.stringify( attName ) +
                `, { cast: conv_enum(${JSON.stringify(type)}), init: ${JSON.stringify(init)} });` );
            buildViewAttribsInit( attName, init, code );
        } else {
            switch ( type ) {
            case 'action':
                code.actions.push( attName );
                code.section.attribs.define.push(
                    "pm.createAction(" + JSON.stringify( attName ) + ")" );
                break;
            case 'any':
                code.section.attribs.define.push(
                    "pm.create(" + JSON.stringify( attName ) + ");" );
                buildViewAttribsInit( attName, init, code );
                break;
            case 'boolean':
            case 'booleans':
            case 'date':
            case 'color':
            case 'string':
            case 'strings':
            case 'array':
            case 'list':
            case 'intl':
            case 'time':
            case 'unit':
            case 'units':
            case 'multilang':
            case 'validator':
                requireConverter = true;
                code.vars[ "conv_" + type ] = "Converters.get('" + type + "')";
                code.section.attribs.define.push(
                    "pm.create(" + JSON.stringify( attName ) +
                    ", { cast: conv_" + type + " });" );
                buildViewAttribsInit( attName, init, code );
                break;
            case 'integer':
            case 'float':
                requireConverter = true;
                code.vars[ "conv_" + type ] = "Converters.get('" + type + "')";
                // Is Not a number, take this default value.
                let nanValue = attValue.default;
                if ( typeof nanValue !== 'number' || isNaN( nanValue ) ) {
                    nanValue = 0;
                }
                code.section.attribs.define.push(
                    "pm.create(" + JSON.stringify( attName ) +
                    ", { cast: conv_" + type + "(" + nanValue + ") });" );
                buildViewAttribsInit( attName, init, code );
                break;
            default:
                throw "Unknown type \"" + type + "\" for attribute \"" + attName + "\"!";
            }
        }

        if ( requireConverter ) {
            code.requires.Converters = "require('tfw.binding.converters')";
        }
    } catch ( ex ) {
        bubble(
            ex,
            `buildViewAttribsSpecial(${attName}: ${JSON.stringify(attValue)})`
        );
    }
}
function buildViewAttribsSpecial ( attName , attValue , code ) { const type = attValue [ 0 ] , init = attValue [ 1 ] ; let requireConverter = false ; try { if ( typeof attValue . behind !== 'undefined' ) { buildViewAttribsSpecialCodeBehind ( attName , attValue . behind , code ) ; } if ( typeof attValue . debug !== 'undefined' ) { buildViewAttribsSpecialDebug ( attName , attValue . debug , code ) ; } if ( Array . isArray ( type ) ) { // Enumerate. code . addCast ( "enum" ) ; code . section . attribs . define . push ( "pm.create(" + JSON . stringify ( attName ) + ` ${ JSON . stringify ( type ) } ${ JSON . stringify ( init ) } ` ) ; buildViewAttribsInit ( attName , init , code ) ; } else { switch ( type ) { case 'action' : code . actions . push ( attName ) ; code . section . attribs . define . push ( "pm.createAction(" + JSON . stringify ( attName ) + ")" ) ; break ; case 'any' : code . section . attribs . define . push ( "pm.create(" + JSON . stringify ( attName ) + ");" ) ; buildViewAttribsInit ( attName , init , code ) ; break ; case 'boolean' : case 'booleans' : case 'date' : case 'color' : case 'string' : case 'strings' : case 'array' : case 'list' : case 'intl' : case 'time' : case 'unit' : case 'units' : case 'multilang' : case 'validator' : requireConverter = true ; code . vars [ "conv_" + type ] = "Converters.get('" + type + "')" ; code . section . attribs . define . push ( "pm.create(" + JSON . stringify ( attName ) + ", { cast: conv_" + type + " });" ) ; buildViewAttribsInit ( attName , init , code ) ; break ; case 'integer' : case 'float' : requireConverter = true ; code . vars [ "conv_" + type ] = "Converters.get('" + type + "')" ; // Is Not a number, take this default value. let nanValue = attValue . default ; if ( typeof nanValue !== 'number' || isNaN ( nanValue ) ) { nanValue = 0 ; } code . section . attribs . define . push ( "pm.create(" + JSON . stringify ( attName ) + ", { cast: conv_" + type + "(" + nanValue + ") });" ) ; buildViewAttribsInit ( attName , init , code ) ; break ; default : throw "Unknown type \"" + type + "\" for attribute \"" + attName + "\"!" ; } } if ( requireConverter ) { code . requires . Converters = "require('tfw.binding.converters')" ; } } catch ( ex ) { bubble ( ex , ` ${ attName } ${ JSON . stringify ( attValue ) } ` ) ; } }
Attribute with casting.
@example
type: {[default, primary, secondary]}
count: {integer}
content: {string ok behind: onContentChanged}
Attribute with casting .