js/foundation/json_renderer/json_renderer.js in rsence-pre-2.2.0.36 vs js/foundation/json_renderer/json_renderer.js in rsence-pre-2.2.0.37

- old
+ new

@@ -22,11 +22,11 @@ ** features and documentation as it matures. ***/ //var//RSence.Foundation COMM.JSONRenderer = HClass.extend({ - version: 0.9, + version: 1.0, /** = Description * Renders JSON structured data, see some of the demos for usage examples. * * = Parameters: @@ -35,16 +35,53 @@ **/ constructor: function(_data, _parent){ if((_data['type'] === 'GUITree') && (this.version >= _data['version'])){ this.data = _data; this.parent = _parent; + this.byId = {}; + this.byName = {}; this.render(); + var _rndr = this; + if( this.view.hasAncestor( HApplication ) ){ + this.view.getViewbyId = function(_id){ return _rndr.getViewById(_id); }; + this.view.getViewsbyName = function(_id){ return _rndr.getViewsByName(_id); }; + } + else if ( this.view.hasAncestor( HView ) ){ + this.view.app.getViewbyId = function(_id){ return _rndr.getViewById(_id); }; + this.view.app.getViewsbyName = function(_id){ return _rndr.getViewsByName(_id); }; + } } else{ throw("JSONRenderer: Only GUITree version "+this.version+" or older data can be handled."); } }, + getViewById: function(_id){ + if( this.byId[_id] !== undefined ){ + return this.byId[_id]; + } + console.log('JSONRenderer; no such view Id: '+_id); + return null; + }, + addViewId: function(_id, _view){ + if( this.byId[_id] !== undefined ){ + console.log('JSONRenderer; already has id: '+_id+' (replacing)'); + } + this.byId[_id] = _view; + }, + getViewsByName: function(_name){ + if( this.byName[_id] !== undefined ){ + return this.byName[_name]; + } + console.log('JSONRenderer; no views named: '+_name); + return []; + }, + addViewName: function(_name, _view){ + if( this.byName[_name] === undefined ){ + this.byName[_name] = []; + } + this.byName[_name].push(_view); + }, render: function(){ this.scopes = [window]; this.scopeDepth = 0; this.view = this.renderNode( this.data, this.parent ); }, @@ -139,15 +176,45 @@ } else { return (new _class(_args)); } }, + _handleCall: function( _instance, _call ){ + if( _call instanceof Object ){ + var + _methodName, _arguments; + for( _methodName in _call ){ + // console.log('methodName:',_methodName); + if( typeof _instance[_methodName] === 'function' ){ + // console.log('callArguments:',_call[_methodName]); + try{ + _instance[_methodName].apply( _instance, _call[_methodName] ); + } + catch(e){ + console.log('JSONRenderer handleCall error:',e.toString()+', method:',_instance[_methodName],', call args:', _call[_methodName],', e:',e); + } + } + else { + console.log('JSONRenderer handleCall error; undefined method: ',_methodName); + } + } + } + else { + console.log('JSONRenderer handleCall error, unable to handle call format: ',_call); + } + }, renderNode: function( _dataNode, _parent ){ var _reserved = [ 'type', 'args', 'version', 'class', 'rect', 'bind', 'extend', 'options', 'subviews', 'define' ], _className, _class, _origNode, _straightParams = false, _rect, _hasRect, _hasSubviews, _subViews, _hasOptions, _options, _hasExtension, _extension, _hasBind, _bind, + _hasName, _hasId, + _isAppClass = false, _isViewClass = false, + _autoOptionItems = [ + 'label', 'style', 'visible', 'theme', 'html', + 'value', 'enabled', 'events', 'active', 'minValue', 'maxValue' + ], _autoOptionItem, _hasCall, _call, _hasDefinition, _definition, _instance, i, _subView = null; // The name of the class: if( !_dataNode['class'] ){ @@ -164,30 +231,52 @@ else { _className = _dataNode['class']; } _class = this.findInScope( _className ); + + if (_class['hasAncestor'] !== undefined){ + _isAppClass = _class.hasAncestor( HApplication ); + _isViewClass = _class.hasAncestor( HView ); + } + _hasId = ( _dataNode['id'] !== undefined ) && ( typeof _dataNode['id'] === 'string' ); + _hasName = ( _dataNode['name'] !== undefined ) && ( typeof _dataNode['name'] === 'string' ); + if( _straightParams ){ - return this.initStraight( _class, _dataNode ); + _instance = this.initStraight( _class, _dataNode ); } else if( _dataNode['args'] !== undefined ){ - return this.initStraight( _class, _dataNode['args'] ); + _instance = this.initStraight( _class, _dataNode['args'] ); } else if( _origNode && _origNode['args'] !== undefined ){ - return this.initStraight( _class, _origNode['args'] ); + _instance = this.initStraight( _class, _origNode['args'] ); } + if( _instance ){ + if( _hasId ){ + this.addViewId( _dataNode.id, _instance ); + } + if( _hasName ){ + this.addViewName( _dataNode.id, _instance ); + } + return _instance; + } - // Currently only HView -derived classes are supported, so + // Currently only HView -derived classes are supported, so // the rect is mandatory. _rect = _dataNode['rect']; _hasRect = (_rect !== undefined) && (_rect instanceof Array || typeof _rect === 'string'); if( !_hasRect && _origNode){ _hasRect = _origNode['rect'] !== undefined; _rect = _hasRect?_origNode['rect']:null; } - + if( !_isViewClass ){ + if( _hasRect ){ + console.log( "renderNode warning; Supposedly rect-incompatible class supplied: "+_className ); + } + } + // Checks, if any sub-views are defined. _hasSubviews = _dataNode['subviews'] !== undefined; _subViews = _hasSubviews?_dataNode['subviews']:null; if( !_hasSubviews && _origNode){ _hasSubviews = _origNode['subviews'] !== undefined; @@ -199,10 +288,20 @@ _options = _hasOptions?_dataNode['options']:null; if( !_hasOptions && _origNode){ _hasOptions = _origNode['options'] !== undefined; _options = _hasOptions?_origNode['options']:null; } + for( i=0; i < _autoOptionItems.length; i++ ){ + _autoOptionItem = _autoOptionItems[i]; + if( _dataNode[ _autoOptionItem ] !== undefined ){ + if( !_hasOptions ){ + _hasOptions = true; + _options = {}; + } + _options[_autoOptionItem] = _dataNode[ _autoOptionItem ]; + } + } // JS Extension block _hasExtension = _dataNode['extend'] !== undefined; _extension = _hasExtension?_dataNode['extend']:null; if( !_hasExtension && _origNode){ @@ -215,19 +314,27 @@ _bind = _hasBind?_dataNode['bind']:null; if( !_hasBind && _origNode){ _hasBind = _origNode['bind'] !== undefined; _bind = _hasBind?_origNode['bind']:null; } + + _hasCall = _dataNode['call'] !== undefined; + if( _hasCall ){ + _call = _dataNode['call']; + } // JS Definition block _hasDefinition = _dataNode['define'] !== undefined; _definitions = _hasDefinition?_dataNode['define']:null; if( !_hasDefinition && _origNode){ _hasDefinition = _origNode['define'] !== undefined; _definitions = _hasDefinition?_origNode['define']:null; } - + if( _rect === null && _class['hasAncestor'] && _class.hasAncestor( HView ) ) { + console.log( 'Ancestors include HView, but no rect defined!' ); + } + // The HView-derived class instance, instance is by default the parent _instance = _parent; this.scopeDepth ++; this.scopes.push({}); @@ -278,17 +385,39 @@ _options.valueObj = COMM.Values.values[_options['valueObjId']]; } } } // For HApplication -derived classes - if(!_hasRect && _hasOptions){ - _instance = _class.nu(_options); + if( _isAppClass ){ + if( _hasOptions ){ + _instance = _class.nu( _options ); + } + else { + _instance = _class.nu(); + } } - // For HView and HControl -derived classes - else if(_hasRect){ - _instance = _class.nu(_rect,_parent,_options); + else if ( _isViewClass ){ + _instance = _class.nu( _rect, _parent, _options ); } + else { + if( _hasRect ){ + if( _hasOptions ){ + _instance = _class.nu(_rect,_parent,_options); + } + else { + _instance = _class.nu(_rect,_parent); + } + } + else if ( _hasOptions ){ + // console.log(_className,_parent,_options); + _instance = _class.nu( _parent, _options ); + } + else { + // console.log('renderNode warning; unsure how to construct: '+_className+', rect:',_rect,', options:',_options); + _instance = _class.nu( _parent ); + } + } if(!_hasOptions){ if(_hasBind){ if( _bind instanceof HValue ){ _bind.bind( _instance ); } @@ -302,11 +431,20 @@ } } else if(!(!_class && _hasSubviews)) { console.log('renderNode warning; No such class: '+_className+', node: ',_dataNode); } + if( _hasId ){ + this.addViewId( _dataNode.id, _instance ); + } + if( _hasName ){ + this.addViewName( _dataNode.id, _instance ); + } + if(_hasCall){ + this._handleCall(_instance,_call); + } } - catch(e){ + catch (e){ console.log('renderNode error:',e.toString()+', rect:',_rect,', class:',_dataNode['class'],', options:', _options,', e:',e); } // Iterates recursively through all subviews, if specified. if(_hasSubviews){ for( i = 0; i < _subViews.length; i++ ){