#if COPYRIGHT //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //------------------------------------------------------------------------------ #endif Sys.Component = function() { /// Base class for Control, Behavior and any object that wants its lifetime to be managed. if (Sys.Application) Sys.Application.registerDisposableObject(this); } Sys.Component.prototype = { _id: null, ##DEBUG _idSet: false, _initialized: false, _updating: false, get_events: function() { /// /// The collection of event handlers for this behavior. /// This property should only be used by derived behaviors /// and should not be publicly called by other code. /// if (!this._events) { this._events = new Sys.EventHandlerList(); } return this._events; }, get_id: function() { /// return this._id; }, set_id: function(value) { #if DEBUG if (this._idSet) throw Error.invalidOperation(Sys.Res.componentCantSetIdTwice); this._idSet = true; var oldId = this.get_id(); if (oldId && Sys.Application.findComponent(oldId)) throw Error.invalidOperation(Sys.Res.componentCantSetIdAfterAddedToApp); #endif this._id = value; }, get_isInitialized: function() { /// return this._initialized; }, get_isUpdating: function() { /// return this._updating; }, add_disposing: function(handler) { this.get_events().addHandler("disposing", handler); }, remove_disposing: function(handler) { this.get_events().removeHandler("disposing", handler); }, add_propertyChanged: function(handler) { this.get_events().addHandler("propertyChanged", handler); }, remove_propertyChanged: function(handler) { this.get_events().removeHandler("propertyChanged", handler); }, beginUpdate: function() { this._updating = true; }, dispose: function() { if (this._events) { var handler = this._events.getHandler("disposing"); if (handler) { handler(this, Sys.EventArgs.Empty); } } delete this._events; Sys.Application.unregisterDisposableObject(this); Sys.Application.removeComponent(this); }, endUpdate: function() { this._updating = false; if (!this._initialized) this.initialize(); this.updated(); }, initialize: function() { this._initialized = true; }, raisePropertyChanged: function(propertyName) { /// Raises a change notification event. /// The name of the property that changed. if (!this._events) return; var handler = this._events.getHandler("propertyChanged"); if (handler) { handler(this, new Sys.PropertyChangedEventArgs(propertyName)); } }, updated: function() { } } Sys.Component.registerClass('Sys.Component', null, Sys.IDisposable, Sys.INotifyPropertyChange, Sys.INotifyDisposing); function Sys$Component$_setProperties(target, properties) { /// Recursively sets properties on an object. /// The object on which to set the property values. /// A JSON object containing the property values. var current; var targetType = Object.getType(target); var isObject = (targetType === Object) || (targetType === Sys.UI.DomElement); var isComponent = Sys.Component.isInstanceOfType(target) && !target.get_isUpdating(); if (isComponent) target.beginUpdate(); for (var name in properties) { var val = properties[name]; var getter = isObject ? null : target["get_" + name]; if (isObject || typeof(getter) !== 'function') { // No getter, looking for an existing field. var targetVal = target[name]; ##DEBUG if (!isObject && typeof(targetVal) === 'undefined') throw Error.invalidOperation(String.format(Sys.Res.propertyUndefined, name)); if (!val || (typeof(val) !== 'object') || (isObject && !targetVal)) { target[name] = val; } else { Sys$Component$_setProperties(targetVal, val); } } else { var setter = target["set_" + name]; if (typeof(setter) === 'function') { // The setter exists, using it in all cases. setter.apply(target, [val]); } else if (val instanceof Array) { // There is a getter but no setter and the value to set is an array. Adding to the existing array. current = getter.apply(target); ##DEBUG if (!(current instanceof Array)) throw new Error.invalidOperation(String.format(Sys.Res.propertyNotAnArray, name)); for (var i = 0, j = current.length, l= val.length; i < l; i++, j++) { current[j] = val[i]; } } else if ((typeof(val) === 'object') && (Object.getType(val) === Object)) { // There is a getter but no setter and the value to set is a plain object. Adding to the existing object. current = getter.apply(target); ##DEBUG if ((typeof(current) === 'undefined') || (current === null)) throw new Error.invalidOperation(String.format(Sys.Res.propertyNullOrUndefined, name)); Sys$Component$_setProperties(current, val); } #if DEBUG else { // No setter, and the value is not an array or object, throwing. throw new Error.invalidOperation(String.format(Sys.Res.propertyNotWritable, name)); } #endif } } if (isComponent) target.endUpdate(); } function Sys$Component$_setReferences(component, references) { for (var name in references) { var setter = component["set_" + name]; var reference = $find(references[name]); #if DEBUG if (typeof(setter) !== 'function') throw new Error.invalidOperation(String.format(Sys.Res.propertyNotWritable, name)); if (!reference) throw Error.invalidOperation(String.format(Sys.Res.referenceNotFound, references[name])); #endif setter.apply(component, [reference]); } } var $create = Sys.Component.create = function(type, properties, events, references, element) { /// /// Instantiates a component of the specified type, attaches it to the specified element if it's /// a Control or Behavior, sets the properties as described by the specified JSON object, /// then calls initialize. /// /// The type of the component to create. /// /// A JSON object that describes the properties and their values. /// /// /// A JSON object that describes the events and their handlers. /// /// /// A JSON object that describes the properties that are references to other components. /// The contents of this object consists of name/id pairs. /// If in a two-pass creation, the setting of these properties will be delayed until the second pass. /// /// /// The DOM element the component must be attached to. /// /// The component instance. #if DEBUG if (!type.inheritsFrom(Sys.Component)) { throw Error.argument('type', String.format(Sys.Res.createNotComponent, type.getName())); } if (type.inheritsFrom(Sys.UI.Behavior) || type.inheritsFrom(Sys.UI.Control)) { if (!element) throw Error.argument('element', Sys.Res.createNoDom); } else if (element) throw Error.argument('element', Sys.Res.createComponentOnDom); #endif var component = (element ? new type(element): new type()); var app = Sys.Application; var creatingComponents = app.get_isCreatingComponents(); component.beginUpdate(); if (properties) { Sys$Component$_setProperties(component, properties); } if (events) { for (var name in events) { #if DEBUG if (!(component["add_" + name] instanceof Function)) throw new Error.invalidOperation(String.format(Sys.Res.undefinedEvent, name)); if (!(events[name] instanceof Function)) throw new Error.invalidOperation(Sys.Res.eventHandlerNotFunction); #endif component["add_" + name](events[name]); } } if (component.get_id()) { app.addComponent(component); } if (creatingComponents) { // DevDiv 81690: Do not add to createdComponent list unless we are in 2 pass mode, // which is during the first GET and on partial updates. app._createdComponents[app._createdComponents.length] = component; if (references) { app._addComponentToSecondPass(component, references); } else { component.endUpdate(); } } else { if (references) { Sys$Component$_setReferences(component, references); } component.endUpdate(); } return component; }