docs: function( params ){
        var defaults = { 
          field: 'data',
          bindingEvent: 'data',
          allowBinding: false,
          allowSetting: false,
          allowGetting: false,
          settingEvent: 'data',
          settingTriggersEvent: false,
          triggerFnName: 'trigger',
          immutableKeys: {}, // key => true if immutable
          updateMappers: false,
          onSet: function( self ){},
          canSet: function( self ){ return true }
        };
        params = $$.util.extend({}, defaults, params);
  
        return function dataImpl( name, value ){
          var p = params;
          var self = this;
          var selfIsArrayLike = self.length !== undefined;
          var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
          var single = selfIsArrayLike ? self[0] : self;
  
          // .data('foo', ...)
          if( $$.is.string(name) ){ // set or get property
  
            // .data('foo')
            if( p.allowGetting && value === undefined ){ // get
  
              var ret;
              if( single ){
                ret = single._private[ p.field ][ name ];
              }
              return ret;
            
            // .data('foo', 'bar')
            } else if( p.allowSetting && value !== undefined ) { // set
              var valid = !p.immutableKeys[name];
              if( valid ){
                for( var i = 0, l = all.length; i < l; i++ ){
                  if( p.canSet( all[i] ) ){
                    all[i]._private[ p.field ][ name ] = value;
                  }
                }
  
                // update mappers if asked
                if( p.updateMappers ){ self.updateMappers(); }
  
                // call onSet callback
                p.onSet( self );
  
                if( p.settingTriggersEvent ){
                  self[ p.triggerFnName ]( p.settingEvent );
                }
              }
            }
  
          // .data({ 'foo': 'bar' })
          } else if( p.allowSetting && $$.is.plainObject(name) ){ // extend
            var obj = name;
            var k, v;
  
            for( k in obj ){
              v = obj[ k ];
  
              var valid = !p.immutableKeys[k];
              if( valid ){
                for( var i = 0, l = all.length; i < l; i++ ){
                  if( p.canSet( all[i] ) ){
                    all[i]._private[ p.field ][ k ] = v;
                  }
                }
              }
            }
            
            // update mappers if asked
            if( p.updateMappers ){ self.updateMappers(); }
  
            // call onSet callback
            p.onSet( self );
  
            if( p.settingTriggersEvent ){
              self[ p.triggerFnName ]( p.settingEvent );
            }
          
          // .data(function(){ ... })
          } else if( p.allowBinding && $$.is.fn(name) ){ // bind to event
            var fn = name;
            self.bind( p.bindingEvent, fn );
          
          // .data()
          } else if( p.allowGetting && name === undefined ){ // get whole object
            var ret;
            if( single ){
              ret = single._private[ p.field ];
            }
            return ret;
          }
  
          return self; // maintain chainability
        }; // function
      }