nv-data-selection
============
- nv-data-selection ,nest selection
- multi, radio,value,validator 
- notifier callback

install
=======
- npm install nv-data-selection

usage
=====

        const x = require("nv-data-selection")

example
-------

    //Json CFG
    //   T@required : String         OPTION-TAG
    //   A@optional : O              OPTION-ATTRIB
    //   - if A-NOT-exist , type-will-be-treated-as-Value AND T-will-be-treated-as-<string>value
    //       O : {
    //           type: 'Multi' | 'Radio' | 'Value' | 'Setter';
    //           val?: any if(type-is-Value AND value-not-string);
    //           validate?: (v,self)=>Boolean  if(type-is-setter);  
    //           as?: 'ary' | 'dict'   if(type-is-Multi);        // as-array OR as-value when .val_ when Multi 
    //           slcted: Boolean                      
    //       }               
    //   C@optional : Array<...S>    NEST-CHILD
    //   S : [T,A?,C?]

    var J = [
         'color', {type:'Multi',as:'ary'},[
              'blue',
              'yellow',
              'green',
              'radio',{type:"Radio"},[
                   "white",
                   "black"
              ],
              'other',{type:"Setter",validate:function(clr) {return(["red","grey","purple"].includes(clr))}}
         ]
    ]



    var [rt,forest] = x.load_from_json(J)
    //watcher slct/unslct
    //rt.regis_$noti$((src,self)=>{console.log(src,self.json())})

        > console.dir(rt.json(),{depth:null})
        [
          'color',
          { type: 'Multi', as: 'ary', slcted: true },
          [
            'blue',
            'yellow',
            'green',
            'radio',
            { type: 'Radio' },
            [ 'white', 'black' ],
            'other',
            { type: 'Setter', validate: [Function: validate] }
          ]
        ]

        > rt.val_
        { color: [] }
        >

        rt.color.yellow.slct_self()


        rt.color.radio.slct_self()
        rt.color.radio.white.slct_self()

        rt.color.other.slct_self()
        rt.color.other.val_ = 'grey'

        > rt.val_
        { color: [ 'yellow', 'white', 'grey' ] }
        >


        > rt.tree()
        {
          color: { yellow: 'yellow', radio: { white: 'white' }, other: 'grey' }
        }
        >
        > console.dir(rt.json(),{depth:null})
        [
          'color',
          { type: 'Multi', as: 'ary', slcted: true },
          [
            'blue',
            'yellow',
            { slcted: true },
            'green',
            'radio',
            { type: 'Radio', slcted: true },
            [ 'white', { slcted: true }, 'black' ],
            'other',
            {
              type: 'Setter',
              val: 'grey',
              validate: [Function: validate],
              slcted: true
            }
          ]
        ]

        > rt.color.radio.black.slct_self()
        Option [ Value : <slcted> ] {}
        >
        > rt.val_
        { color: [ 'yellow', 'black', 'grey' ] }
        >
        > rt.color.other.unslct_self()
        Option [ Setter : <unslcted> ] {}
        > rt.val_
        { color: [ 'yellow', 'black' ] }
        >
        > rt.color.radio.black.unslct_self()
        Option [ Value : <unslcted> ] {}
        >
        > rt.val_
        { color: [ 'yellow' ] }
        >



### use array-irs


     const {slcted_multi_as_dict,slcted_vali,slcted_radio,slcted_radio_bool_dflt_tru,slcted_vali_any} = x.IR;

     const {is_ipv4_addr,is_port,is_url_abs_pathname,is_url_abs_path,is_url_abs_path} = x.vali_func;
     const is_str = (s)=>typeof(s)==='string';


     const DFLT_EDITOR = slcted_multi_as_dict(
           'Device',[
              ...slcted_vali('name',is_str,'door'),
              ...slcted_vali('code',is_str),
              ...slcted_radio('type',[
                  '进口','出口'
              ]),
              ...slcted_radio_bool_dflt_tru('upload'),
              ...slcted_multi_as_dict(
                  'led',[
                      ...slcted_radio_bool_dflt_tru('use'),
                      ...slcted_vali('addr',is_ipv4_addr),
                      ...slcted_vali('user',is_str),
                      ...slcted_vali('pass',is_str),
                      ...slcted_vali_any('status'),
                      ...slcted_vali('sdkport',is_port)
                   ]
              ),
              ...slcted_multi_as_dict(
                  'bar',[
                     ...slcted_vali('addr',is_ipv4_addr),
                     ...slcted_vali_any('status'),
                  ]
              ),
              ...slcted_multi_as_dict(
                   'incamjk',[
                       ...slcted_radio_bool_dflt_tru('use'),
                       ...slcted_vali('addr',is_ipv4_addr),
                       ...slcted_vali('user',is_str),
                       ...slcted_vali('pass',is_str),
                       ...slcted_vali_any('status'),
                       ...slcted_vali('sdkport',is_port),
                       ...slcted_vali('viewport',is_port)
                   ]
              ),
              ...slcted_multi_as_dict(
                   'incamzp',[
                       ...slcted_radio_bool_dflt_tru('use'),
                       ...slcted_vali('addr',is_ipv4_addr),
                       ...slcted_vali('user',is_str),
                       ...slcted_vali('pass',is_str),
                       ...slcted_vali_any('status'),
                       ...slcted_vali('sdkport',is_port),
                       ...slcted_vali('viewport',is_port),
                       ...slcted_vali('ISAPI_barr',is_url_abs_pathname),
                       ...slcted_vali('ISAPI_led1',is_url_abs_path),
                       ...slcted_vali('ISAPI_led2',is_url_abs_path),
                   ]
              ),
              ...slcted_multi_as_dict(
                   'outcamjk',[
                       ...slcted_radio_bool_dflt_tru('use'),
                       ...slcted_vali('addr',is_ipv4_addr),
                       ...slcted_vali('user',is_str),
                       ...slcted_vali('pass',is_str),
                       ...slcted_vali_any('status'),
                       ...slcted_vali('sdkport',is_port),
                       ...slcted_vali('viewport',is_port)
                   ]
              ),
              ...slcted_multi_as_dict(
                   'outcamzp',[
                       ...slcted_radio_bool_dflt_tru('use'),
                       ...slcted_vali('addr',is_ipv4_addr),
                       ...slcted_vali('user',is_str),
                       ...slcted_vali('pass',is_str),
                       ...slcted_vali_any('status'),
                       ...slcted_vali('sdkport',is_port),
                       ...slcted_vali('viewport',is_port),
                       ...slcted_vali('ISAPI_barr',is_url_abs_pathname),
                       ...slcted_vali('ISAPI_led1',is_url_abs_path),
                       ...slcted_vali('ISAPI_led2',is_url_abs_path),
                   ]
              )
           ]
        )

        var [opts,forest] = x.load_from_json(DFLT_EDITOR)

        > opts.val_
        {
          Device: {
            name: 'door',
            upload: true,
            led: { use: true, status: undefined },
            bar: { status: undefined },
            incamjk: { use: true, status: undefined },
            incamzp: { use: true, status: undefined },
            outcamjk: { use: true, status: undefined },
            outcamzp: { use: true, status: undefined }
          }
        }
        >


        opts.Device.led.addr                                    opts.Device.led.pass                                    opts.Device.led.sdkport                                 opts.Device.led.status
        opts.Device.led.use                                     opts.Device.led.user

        > opts.Device.led.addr = '198.1.1'
        '198.1.1'
        >
        > opts.val_
        {
          Device: {
            name: 'door',
            upload: true,
            led: { use: true, status: undefined },
            bar: { status: undefined },
            incamjk: { use: true, status: undefined },
            incamzp: { use: true, status: undefined },
            outcamjk: { use: true, status: undefined },
            outcamzp: { use: true, status: undefined }
          }
        }
        > opts.Device.led.addr.val_ = '198.1.1'
        setter_validate_failed
        '198.1.1'
        >
        > opts.Device.led.addr.val_ = '198.1.1.1'
        '198.1.1.1'
        >
        > opts.val_
        {
          Device: {
            name: 'door',
            upload: true,
            led: { use: true, addr: '198.1.1.1', status: undefined },
            bar: { status: undefined },
            incamjk: { use: true, status: undefined },
            incamzp: { use: true, status: undefined },
            outcamjk: { use: true, status: undefined },
            outcamzp: { use: true, status: undefined }
          }
        }
        >




        > opts.Device.type.出口.slct_self()
        Option [ Value : <slcted> ] {}
        >
        >
        > opts.val_
        {
          Device: {
            name: 'door',
            type: '出口',
            upload: true,
            led: { use: true, addr: '198.1.1.1', status: undefined },
            bar: { status: undefined },
            incamjk: { use: true, status: undefined },
            incamzp: { use: true, status: undefined },
            outcamjk: { use: true, status: undefined },
            outcamzp: { use: true, status: undefined }
          }
        }
        >



APIS
====
- load\_from\_json(jcfg)

### IRS


        {
          _V: [Function: _V],
          _m: [Function: _m],
          _r: [Function: _r],
          _v: [Function: _v],
          value: [Function: value],
          vali: [Function: vali],
          radio: [Function: radio],
          multi: [Function: multi],
          multi_as_dict: [Function: multi_as_dict],
          multi_as_ary: [Function: multi_as_ary],
          slcted_value: [Function: slcted_value],
          unslcted_value: [Function: unslcted_value],
          slcted_vali: [Function: slcted_vali],
          unslcted_vali: [Function: unslcted_vali],
          slcted_radio: [Function: slcted_radio],
          unslcted_radio: [Function: unslcted_radio],
          slcted_multi_as_dict: [Function: slcted_multi_as_dict],
          slcted_multi_as_ary: [Function: slcted_multi_as_ary],
          unslcted_multi_as_dict: [Function: unslcted_multi_as_dict],
          unslcted_multi_as_ary: [Function: unslcted_multi_as_ary],
          tru: [Function: tru],
          fls: [Function: fls],
          slcted_tru: [Function: slcted_tru],
          unslcted_tru: [Function: unslcted_tru],
          slcted_fls: [Function: slcted_fls],
          unslcted_fls: [Function: unslcted_fls],
          '$tru': [Function: $tru],
          '$fls': [Function: $fls],
          slcted_radio_bool: [Function: slcted_radio_bool],
          unslcted_radio_bool: [Function: unslcted_radio_bool],
          slcted_radio_bool_dflt_tru: [Function: slcted_radio_bool_dflt_tru],
          slcted_radio_bool_dflt_fls: [Function: slcted_radio_bool_dflt_fls],
          unslcted_radio_bool_dflt_tru: [Function: unslcted_radio_bool_dflt_tru],
          unslcted_radio_bool_dflt_fls: [Function: unslcted_radio_bool_dflt_fls],
          slcted_vali_any: [Function: slcted_vali_any],
          unslcted_vali_any: [Function: unslcted_vali_any],
          slcted_vali_none: [Function: slcted_vali_none],
          unslcted_vali_none: [Function: unslcted_vali_none]
        }




methods
-------

        nd.regis_$noti$(f=(srcnd,msg,self)=>{})
        nd.regis_$validate$(f=(v,self)=>true)


        nd.change_$type_to_multi$()                  
        nd.change_$type_to_radio$()

        //
        nd.val_       //get calculated value

        //on self
        nd.as_
        nd.chks_                //children-keys
        nd.key_ 
        nd.type_
        nd.is_slcted()
        nd.json()                    //detail info
        nd.tree()                    //slcted brief info                                     
        nd.slct_self()
        nd.unslct_self()

        //for Value abd Setter assign
        nd.val_ =

        //for Setter
        nd.validate_ nd.validate_ = 

        
        //for Radio and Multi
        nd.opts_                                   
        nd.slct_child(which)                              
        nd.unslct_child(which)


        //for Multi
        nd.set_$as_dict$()
        nd.set_$as_ary$()             //default  
        nd.slct_all_children()
        nd.unslct_all_children()
        nd.slcted_children_ 
        nd.unslcted_children_

LICENSE
=======
- ISC 
