function greet(message) {
alert(message + ", " + this.name);
}
var instance = { name: "fred" };
//when you create a delegate, "this" in the delegate function body
//refer to the instance passed in
var greetSomeone = Function.createDelegate(instance, greet);
greetSomeone("hello");
/*
Function.createDelegate = function Function$createDelegate(instance, method) {
///
///
///
///
var e = Function._validateParams(arguments, [
{ name: "instance", mayBeNull: true },
{ name: "method", type: Function }
]);
if (e) throw e;
return function() {
return method.apply(instance, arguments);
}
}
Mar 16, 2009
Function.createDelegate
Function.createCallback
var createCallback = function(method, context) {
return function() {
//the arguements is passed in when the this callback
//method is call
//if there is parameter passed
//package the parameter with the context
//into an array, an invoke the callback
//method with the array
var l = arguments.length;
if (l > 0) {
var args = [];
for (var i = 0; i < l; i++) {
args[i] = arguments[i];
}
//the last array member is the
//the context
args[l] = context;
//apply with array argument
return method.apply(this, args);
}
//if there is no parameters
//just invoke the callback method with
// the context as the only parameter
return method.call(this, context);
}
}
function eat(foodName, animalName) {
alert(animalName + " eat " + foodName);
}
function Animal(name) {
if (!name) {
this.name = name;
}
else {
this.name = "animal";
}
//eat is the function will be called
//name is the predetermined pass-in parameter
//this parameter will be the last parameter in the function
//the order paraemeter will be passed in when the callback is called
this.eat = createCallback(eat, name);
}
var a = new Animal("fred");
//"grass" is passed in when callback is called
a.eat("grass");
Mar 23, 2008
difference between behavior and controls in asp.net
The differences between controls and behaviors are mostly semantic. Both are components associated with DOM elements in the page, and they offer a similar set of features. Behaviors enhance DOM elements without changing the base func- tionality they provide. If you associate a behavior with a text box element, the text field continues to accept the user’s text input. But you can use the behavior to add client functionality to the text box and, for example, upgrade it to an auto-com- plete text box.
The chief purpose of client controls is creating element wrappers. For example, you can create a TextBox control that wraps an input element of type text. You can create a Label control that wraps a span element, and so on. This is similar to what happens with the ASP.NET TextBox and Label server controls. The differ- ence is that they wrap DOM elements on the server side rather than on the client side. An element wrapper can be useful to enhance the way you program against a DOM element. For example, you can use controls as a way to program against DOM elements using declarative code.
A fundamental difference between behaviors and controls is that a DOM ele- ment can have multiple behaviors, but it can be associated with one and only one control. For this reason, behaviors are best suited to add client capabilities to a DOM element in an incremental way. On the other hand, a control is supposed to provide the whole client functionality to its associated element.
Mar 5, 2008
Sys.UI.Control
Conceptually, a control differs from a behavior in the sense that instead of just providing client functionality, a control usually represents or wraps the element, to provide additional properties and methods that extend its programming interface.
Type.registerNamespace('Samples');
Samples.EmptyControl = function(element) {
Samples.EmptyControl.initializeBase(this, [element]);
}
Samples.EmptyControl.prototype = {
initialize : function() {
Samples.EmptyControl.callBaseMethod(this, 'initialize');
},
dispose : function() {
Samples.EmptyControl.callBaseMethod(this, 'dispose');
}
}
Samples.EmptyControl.registerClass('Samples.EmptyControl',
Sys.UI.Control);
//creating controls
$create(Samples.EmptyControl, {}, {}, {}, $get('elementID'));
Because controls are client components, you can access them with the $find method. However, the Id of control can't be set programatically. It is automatically set by the SysUI.Control calss to the same ID as the associated element. You can get a reference to the control by passing the ID of the associated DOM element to $find. Another way to access a control is through the associated element. Because an element can have one or only one associated control, a property called "control", which stores the reference to the control - is created on the DOM element when the control is initialized. Supposing that you have a DOM element stored in the someElement variable, the following statement accesses the associated control arne stores a reference in the controlInstance variable.
var controlInstance = someElement.control;
Below is textbox control's implementation code
Type.registerNamespace('Samples');
// Samples.TextBox class.
Samples.TextBox = function(element) {
Samples.TextBox.initializeBase(this, [element]);
this._ignoreEnterKey = false;
}
Samples.TextBox.prototype = {
// Component lifecycle.
initialize : function() {
Samples.TextBox.callBaseMethod(this, 'initialize');
// Subscribe to the keypress event.
$addHandlers(this.get_element(),
{keypress:this._onKeyPress}, this);
},
dispose : function() {
// Detach event handlers.
$clearHandlers(this.get_element());
Samples.TextBox.callBaseMethod(this, 'dispose');
},
// Handle the keypress event.
_onKeyPress : function(evt) {
if(this._ignoreEnterKey && evt.charCode == 13) {
evt.preventDefault();
}
},
// Properties.
get_ignoreEnterKey : function() {
return this._ignoreEnterKey;
},
set_ignoreEnterKey : function(value) {
this._ignoreEnterKey = value;
}
}
Samples.TextBox.registerClass('Samples.TextBox', Sys.UI.Control);
//at the client side
Sys.Application.add_init(pageInit);
function pageInit() {
$create(Samples.TextBox, {'ignoreEnterKey':true}, {}, {},
$get('myTextBox'));
}
Sys.UI.Behavior
Type.registerNamespace('Samples');
Samples.EmptyBehavior = function(element) {
Samples.EmptyBehavior.initializeBase(this, [element]);
}
Samples.EmptyBehavior.prototype = {
initialize : function() {
Samples.EmptyBehavior.callBaseMethod(this, 'initialize');
},
dispose : function() {
Samples.EmptyBehavior.callBaseMethod(this, 'dispose');
}
}
Samples.EmptyBehavior.registerClass('Samples.EmptyBehavior',
Sys.UI.Behavior);
//Creating behavior
$create(Samples.EmptyBehavior, {'name':'myEmptyBehavior'}, {}, {},
$get('elementID'));
//accessing behaviors
var instance = $find('someElement$myEmptyBehavior');
//or
var emptyBehaviorInstance = $get('someElement').myEmptyBehavior;
Type.registerNamespace('Samples');
// Samples.FormattingBehavior class.
Samples.FormattingBehavior = function(element) {
Samples.FormattingBehavior.initializeBase(this, [element]);
// Fields.
this._hoverCssClass = null;
this._focusCssClass = null;
this._currentCssClass = null;
this._mouseOver = null;
this._focus = null;
}
Samples.FormattingBehavior.prototype = {
// Component lifecycle.
initialize : function() {
Samples.FormattingBehavior.callBaseMethod(this, 'initialize');
//this is changing the
//the behavior of the associated
//element
//get_element is inherit from parent.
$addHandlers(this.get_element(),
{
mouseout:this._onMouseout,
mouseover:this._onMouseover,
focus:this._onFocus,
blur:this._onBlur
}, this);
},
dispose : function() {
$clearHandlers(this.get_element());
Samples.FormattingBehavior.callBaseMethod(this, 'dispose');
},
// Event handlers.
_onMouseover : function() {
this._mouseOver = true;
this._setCssClass();
},
_onMouseout : function() {
this._mouseOver = false;
this._setCssClass();
},
_onFocus : function() {
this._focus = true;
this._setCssClass();
},
_onBlur : function() {
this._focus = false;
this._setCssClass();
},
// Helper method.
_setCssClass : function() {
if (this._currentCssClass) {
Sys.UI.DomElement.removeCssClass(this._element,
this._currentCssClass);
this._currentCssClass = null;
}
if (this._error) {
this._currentCssClass = this._errorCssClass;
}
else if (this._focus) {
this._currentCssClass = this._focusCssClass;
}
else if (this._mouseOver) {
this._currentCssClass = this._hoverCssClass;
}
if (this._currentCssClass) {
Sys.UI.DomElement.addCssClass(this._element,
this._currentCssClass);
}
},
// Properties.
get_hoverCssClass : function() {
return this._hoverCssClass;
},
set_hoverCssClass : function(value) {
this._hoverCssClass = value;
},
get_focusCssClass : function() {
return this._focusCssClass;
},
set_focusCssClass : function(value) {
this._focusCssClass = value;
}
}
// Inherit from Sys.UI.Behavior.
Samples.FormattingBehavior.registerClass('Samples.FormattingBehavior', Sys.UI.Behavior);
//add the client side we attached the behavior to element
Sys.Application.add_init(pageInit);
function pageInit(sender, e) {
// Attach the FormattingBehavior to the txtName textbox.
$create(Samples.FormattingBehavior,
{'hoverCssClass':'field_hover', 'focusCssClass':'field_focus'},
{}, {}, $get('Name'));
// Attach the FormattingBehavior to the txtLastName textbox.
$create(Samples.FormattingBehavior,
{'hoverCssClass':'field_hover', 'focusCssClass':'field_focus'},
{}, {}, $get('LastName'));
}
//$create function will automatically call the initialize method.
expose event in asp.net ajax
- Create a method that adds an event handler.
- Create a method that removes an event handler.
- Create a method that is responsible for raising the event.
Type.registerNamespace('Samples');
Samples.Collection = function() {
this._innerList = [];
// Store an instance of Sys.EventHandlerList.
this._events = null;
}
Samples.Collection.prototype = {
// Add an item to the collection.
add : function(member) {
this._innerList.push(member);
// Raise the itemAdded event.
this._raiseEvent('itemAdded', Sys.EventArgs.Empty);
},
// Return the Sys.EventHandlerList instance.
get_events : function() {
if(!this._events) {
this._events = new Sys.EventHandlerList();
}
return this._events;
},
// Add an handler for the itemAdded event.
add_itemAdded : function(handler) {
this.get_events().addHandler('itemAdded', handler);
},
// Remove an handler for the itemAdded event.
remove_itemAdded : function(handler) {
this.get_events().removeHandler('itemAdded', handler);
},
// Generic function to raise an event.
_raiseEvent : function(eventName, eventArgs) {
var handler = this.get_events().getHandler(eventName);
if (handler) {
if (!eventArgs) {
eventArgs = Sys.EventArgs.Empty;
}
handler(this, eventArgs);
}
}
}
Samples.Collection.registerClass('Samples.Collection');
The same process applies to client components that want to expose events. The only difference is that you don't need to store an instance of Sys.EventHandlersList class in the constructor, because every component inherits it from the base Sys.Component class. You also inherit the get_events method shown above.
Additionally, components expose an event called propertyChanged that can be raised whenever the value of a property changes. This mechanism is useful because you don't have to expose and raise a custom event for each value you want to monitor. Instead you rely on the propertyChanged event, defined in the SysINotifyPropertyChange interface. Whenever the value exposed by a property changes, all you have to do is call the raisePropertyChanged method. This method accepts a string with the name of the property whose value has changed. Below is an example.
Type.registerNamespace('Samples');
Samples.Customer = function() {
Samples.Customer.initializeBase(this);
this._fullName;
}
Samples.Customer.prototype = {
get_fullName : function() {
return this._fullName;
},
set_fullName : function(value) {
if(value != this._fullName) {
this._fullName = value;
this.raisePropertyChanged('fullName');
}
}
}
Samples.Customer.registerClass('Samples.Customer', Sys.Component);
//at the client side you use the following code to subscribe the event as below.
function pageLoad(sender, e) {
var customer = new Samples.Customer();
customer.add_propertyChanged(onPropertyChanged);
customer.set_fullName('John Doe');
}
function onPropertyChanged(sender, e) {
if(e.get_propertyName() == 'fullName') {
alert('New value for the fullName property: ' +
sender.get_fullName());
}
}
Mar 2, 2008
cancel request vs abort reqeust
In asp.net ajax framework, you can cancel request before the request is submitted to the server, you can aborted the request after the request is submitted to the server and before the response is received.
function onInitializeRequest(sender, args){
var prm = Sys.WebForms.PageRequestManager.getInstance();
if (prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'CancelRefresh') {
prm.abortPostBack();
}else if (prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'RefreshButton') {
args.set_cancel(true);
ActivateAlertDiv('visible', 'Still working on previous request.');
}
else if (!prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'RefreshButton') {
ActivateAlertDiv('visible', 'Retrieving headlines.');
}
Feb 25, 2008
Dynamically adding control which can do async postback in UpdatePanel
Precondition, The control needs to have Id, if not the ajax clientside script can not handle it. Then see the following code.
Dim btn As LinkButton = CType(child, LinkButton) AddHandler btn.Click, AddressOf ProcessFilter ''me.UpdatePanel1.Triggers.Add(as 'Dim trigger As UpdatePanelControlTrigger = New UpdatePanelControlTrigger Dim trigger As AsyncPostBackTrigger = New AsyncPostBackTrigger() trigger.ControlID = btn.UniqueID trigger.EventName = "Click" Me.UpdatePanel1.Triggers.Add(trigger)
Aug 27, 2007
javascript delegate callback
class Animal
{
public string Greeting = "Hello,";
public void Greet(string message)
{
Console.WriteLine(this.Greeting + message);
}
}
class Client
{
public SampleDelegate TestDelegate;
public void Demo()
{
Animal a = new Animal();
TestDelegate = new SampleDelegate(a.Greet);
TestDelegate("Ainmal");
}
}
But in javascript , "this" is in the context of caller. In asp.net ajax library, there is a function to create a delegate.
Function.createDelegate = function Function$createDelegate(instance, method)
{
///
///
///
var e = Function._validateParams(arguments, [
{name: "instance", mayBeNull: true},
{name: "method", type: Function}
]);
if (e) throw e;
//it is not the same as return method.apply(instance, arguments);
return function() {
return method.apply(instance, arguments);
}
}
Please note that is return a function pointer, and the function call the method in the context of instance.
function pageLoad() {
// test is a property of the window object.
this.test = "I'm a test string!";
// Create a delegate that points to onButtonClick and pass the
// window object as the first argument.
var clickDelegate = Function.createDelegate(this, onButtonClick);
// Handle the click event with the delegate.
$addHandler($get('testButton'), 'click', clickDelegate);
//if we call, $addHandler($get('testButton'), 'click', onButtonClick);
// the "this" inside of the method will reference to button, and its
//test value is null
}
function onButtonClick() {
// Access the window object.
alert(this.test);
}
The Function.createDelegate method is useful because you don’t have to
store in a global variable—or even in a DOM element—the context that you want
to access in the event handler.
$addHandlers(buttonElement, { click:onButtonClick,
mouseover:onMouseOver }, this);
//"this" is context inside of event
Callback function in asp.net ajax library is similar to delegate, but they solve a different problem. Delegate solve the problem of "this" context, so that it accept instance parameter, the "this" will refer to instance. "this" in Callback function is still in the context of caller. But Callback function accept a context parameter.
Both concept is very useful in ajax, because it is all about reuse. The section of code can be reuse in different "conext"!
Function.createCallback = function Function$createCallback(method, context) {
///
///
///
var e = Function._validateParams(arguments, [
{name: "method", type: Function},
{name: "context", mayBeNull: true}
]);
if (e) throw e;
return function() {
var l = arguments.length;
if (l > 0) {
var args = [];
for (var i = 0; i < l; i++) {
args[i] = arguments[i];
}
args[l] = context;
return method.apply(this, args);
}
return method.call(this, context);
}
}
//example
function pageLoad() {
// The context object.
var context = { date : new Date() };
// Create a callback that points to onButtonClick and pass
// the context object.
var clickCallback =
Function.createCallback(onButtonClick, context);
// Attach a handler to the click event of the button.
$addHandler($get('myButton'), 'click', clickCallback);
}
function onButtonClick(evt, context) {
// Here we can access both the event object and
// the context.
var loadTime = context.date;
var elapsed = new Date() - loadTime;
alert(this);
alert((elapsed / 1000) + ' seconds');
}
Aug 10, 2007
ASP.NET AJAX EVENTS
Sys.Component Event
Raised when the dispose method of the current Component object is called.
Raised when the raisePropertyChanged method of the current Component object is called.
Sys.Application Event
Raised after all scripts have been loaded but before objects are created.
Raised after all scripts have been loaded and after the objects in the application have been created and initialized.
Raised before all objects in the client application are disposed.
Sys.WebForms.PageRequestManager Event
Raised before processing of an asynchronous postback starts and the postback request is sent to the server.
Raised after an asynchronous postback is finished and control has been returned to the browser.
Raised during the initialization of the asynchronous postback.
Raised after all content on the page is refreshed as the result of either a synchronous or an asynchronous postback.
Raised after the response from the server to an asynchronous postback is received but before any content on the page is updated.
Aug 7, 2007
Creating asp.net ajax class
ASP.NET AJAX Class
Notice that the local members are accessed with a prefix of this. The script engine can then scope the lookup to the type and avoid searching any containing scopes. If you do not use this to indicate that the reference is local to the type, you will end up creating objects in the global scope and see errors that can be confusing and time-consuming to track down.
The call to registerClass looks a little odd, as it is on the type being registered. The prototype of the base type in JavaScript has been modified to add type-system support. Once the type is registered, an instance of it can be created and its members called.
The registerClass function actually has three possible parameters: The first one is for the name of the type, the second is for the base type being extended, and the last is to specify any interfaces that the class implements. Instances of using these classes are provided in later examples in this chapter.
JavaScript treats parameters as optional. This can be convenient. Instead of needing to define a bunch of different methods with different names in order to accommodate different combinations of parameters, you can write just one that knows how to process all of the optional inputs. Because the language treats all parameters as optional, however, you need to explicitly check that the inputs are valid for what you are doing. The caller can invoke the function with whatever set of parameters it wants to pass.
ASP.NET AJAX Class
The constructor must explicitly call initializeBase and pass itself, using the this keyword, along with an array of the arguments to pass to the constructor of the base type. The AJAX Library allows you to employ object-oriented principles, but doing so requires that you follow some coding patterns like this. Without the call to initializeBase, when you try to call something on the base type, you will get an error. In Internet Explorer, the message reads: Object doesn't support this property or method. This is not the most helpful message! In Firefox, it fails silently, but if you have the JavaScript console open, an error message is displayed that more explicitly identifies the actual problem: anotherAlbum.get_title is not a function
The call to initializeBase takes care of producing the final type with inheritance semantics in place. The base class constructor is called with the arguments provided. The type system of the AJAX Library also provides some reflection functions that let you explore the relationship between objects.
if(Wrox.ASPAJAX.Samples.TributeAlbum.isInstanceOfType(anAlbum) == false) {
alert("anAlbum is not a TributeAlbum");
}
if (Wrox.ASPAJAX.Samples.TributeAlbum.isInstanceOfType(anotherAlbum) == true) {
alert("anotherAlbum is a TributeAlbum");
}
if (Wrox.ASPAJAX.Samples.TributeAlbum.inheritsFrom(Wrox.ASPAJAX.Samples.Album) ==
true ) {
alert("TributeAlbum inherits from Album");
}
if (Wrox.ASPAJAX.Samples.Album.inheritsFrom(Wrox.ASPAJAX.Samples.TributeAlbum) ==
true) {
alert("Album does not inherit from TributeAlbu7");
}
At first glance, the type references in Listing 4-6 look long. JavaScript doesn’t have the equivalent of the using statement that makes namespaces available to code without being explicit. With a compiled language, the cost of the lookup can be paid when the binary is created and symbolic references are created. In an interpreted language like JavaScript, you can speed up the lookup by providing a shortcut for the long type name by providing aliases that reference the fully qualified name. When you create global object aliases, you defeat the purpose of the namespace containers. Each subsequent lookup can get a little more expensive for every item in the checked scope. The ideal time to create aliases is when something is going to be referenced frequently and you can alias it temporarily, when it will soon go out of scope and the alias will be cleaned up. If the code in Listing 4-6 were going to be run frequently, or if it contained many more calls to the types, it would probably be worth caching a reference to the type and avoid the repeated lookups. Creating a local alias is easy; just declare a variable and assign the type to it. Listing 4-7 demonstrates creating and using aliases for the Album and TributeAlbum types.
var tributeAlbum = Wrox.ASPAJAX.Samples.TributeAlbum;
var album = Wrox.ASPAJAX.Samples.Album;
if(tributeAlbum.isInstanceOfType(anAlbum) == false) {
alert("anAlbum is not a TributeAlbum");
}
if (tributeAlbum.isInstanceOfType(anotherAlbum) == true) {
alert("anotherAlbum is a TributeAlbum");
}
if (tributeAlbum.inheritsFrom(album) == true) {
alert("TributeAlbum inherits from Album");
}
if (album.inheritsFrom(tributeAlbum) == true) {
alert("Album does not inherit from TributeAlbum");
}
The AJAX library provides a method for explicitly calling a base method implementation. This is often used when a derived type wants to take the result from the base type and modify it before returning it to the caller. It is not limited to calling into the base type from a derived type’s implementation. You can also call a base method for an object. In a language like C++, you can cast an object to its base type to access a specific method implementation. Likewise, this pattern in JavaScript lets you access the base method even though JavaScript can’t support the casting semantic for this purpose. In Listing 4-8 (from CallBase.aspx), the TributeAlbum class adds an override for the get_artist method. It calls the base implementation and then prepends it with "TRIBUTE: " before returning it. This is again a slight modification to the previous example of the example using Album and TributeAlbum types
Wrox.ASPAJAX.Samples.TributeAlbum.prototype = {
get_tributeArtist: function() {
return this._tributeArtist;
},
set_tributeArtist: function(tributeArtist) {
this._tributeArtist = tributeArtist;
},
get_artist: function() {
return ("TRIBUTE: " +
Wrox.ASPAJAX.Samples.TributeAlbum.callBaseMethod(this, "get_artist"));
}
}
asp.net ajax namespace
ASP.NET AJAX Namespaces
The call to Type.registerNamespace creates three different objects: Wrox, ASPAJAX, and Samples. The Wrox object contains the ASPAJAX object, which in turn contains the Samples object. The objects all carry some metadata so the type system can identify them as namespaces and use them to hold any other objects that are added to the namespace. The Type.isNamespace function returns a Boolean. The code didn’t create an Album namespace, so for that check, it returns false. The set of global namespaces is retrieved by calling Type.getRootnamespaces. Looping through the returned array and calling getName on each reveals that, in addition to the new Wrox namespace, there is also a Sys namespace. It contains the AJAX Library functionality. Although doing so is not technically required, I recommend using namespaces to organize your own code, even if just to avoid cluttering up the global namespace. Because JavaScript is an interpreter language, the operation of resolving names is expensive. Every time you call a function, the JavaScript engine has to figure out where the code lives. Resolving variables also involves searching the current scope and containing scopes until the reference is resolved. The more global objects you have, the more expensive it is for the script engine to access them. Namespace objects also allow navigating to classes in the hierarchy more readily than would happen in a flat global arrangement. Thus, namespaces offer a performance benefit as well as providing a programmer convenience for grouping functionality. Namespaces by themselves, however, are not much use until your create classes in them that will provide useful functionality.
Aug 5, 2007
Reflection
var g = new Demo.Trees.GrannySmith();
var gt = Demo.Trees.GrannySmith;
var a = new Array(
Demo.Trees.Apple,
Demo.Trees.Tree,
Demo.Trees.Pine,
Demo.Trees.IFruitTree,
Sys.IContainer);
function OnButton1Click()
{
for (var i = 0; i < a.length; i ++)
{
if (a[i].isInstanceOfType(g))
{
alert(gt.getName() + " is a " + a[i].getName() + ".");
}
else alert(gt.getName() + " is not a " + a[i].getName() + ".");
}
}
function OnButton2Click()
{
for (var i = 0; i < a.length; i ++)
{
if (gt.inheritsFrom(a[i]))
{
alert(gt.getName() + " inherits from " + a[i].getName() + ".");
}
else alert(gt.getName() + " does not inherit from " + a[i].getName() + ".");
}
}
function OnButton3Click()
{
for (var i = 0; i < a.length; i ++)
{
if (Type.isInterface(a[i]))
{
if (gt.implementsInterface(a[i]))
{
alert(gt.getName() + " implements the " + a[i].getName() + " interface.");
}
else alert(gt.getName() + " does not implement the " + a[i].getName() + " interface.");
}
else alert(a[i].getName() + " is not an interface.");
}
}
Register namespace, and class
Type.registerNamespace("Demo");
Demo.Person = function(firstName, lastName, emailAddress) {
this._firstName = firstName;
this._lastName = lastName;
this._emailAddress = emailAddress;
}
Demo.Person.prototype = {
getFirstName: function() {
return this._firstName;
},
getLastName: function() {
return this._lastName;
},
getName: function() {
return this._firstName + ' ' + this._lastName;
},
dispose: function() {
alert('bye ' + this.getName());
}
}
Demo.Person.registerClass('Demo.Person', null, Sys.IDisposable);
// Notify ScriptManager that this is the end of the script.
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
Type, window.Type, Function
Function.__typeName = 'Function';
Function.__class = true;
//....
window.Type = Function;
window.__rootNamespaces = [];
window.__registeredTypes = {};
Jul 31, 2007
Sys.Component
Generally, the term component denotes an object that is reusable and can interact with other objects in the context of a framework. The term control, on the other hand, denotes an object that is sort of a specialized component. The main trait that differentiates components and controls is the user interface. Components are non-UI objects; controls are primarily UI-based objects. In the Microsoft AJAX library, the root component class is Sys.Component. The root class for controls is named Control and, guess what, lives in the Sys.UI namespace. In the Microsoft AJAX library, Sys.UI.Control derives from Sys.Component.
Sys.Application
The execution of each asp.net ajax page is controlled by an application object that is intstantiated in the body of the library. Whenever an asp.net ajax page is loaded in the browser, an instance of Sys._Application class is promptly created and assigned to the Sys.Application object: Sys.Application = new Sys._Application();
In additional, each asp.net ajax page is injected with the following script code:
This code is placed immediately after the closing tag of the of the page's form, and it commands the loading of any script files registered for loading with the page's script manager. Sys._Application class derives from Compnent and is the entry point point in the page hierachy to locate client-side components either bound to server controls or programmatically added to the application.
|
Member |
Description |
|---|---|
|
addComponent |
Adds the specified Microsoft AJAX library component to the page hierarchy |
|
beginCreateComponents |
Starts adding new Microsoft AJAX library components to the page |
|
endCreateComponents |
Ends adding new Microsoft AJAX library components to the page |
|
findComponent |
Looks up the specified Microsoft AJAX library component in the page |
|
getComponents |
Gets the list of Microsoft AJAX library components found in the page |
|
initialize |
Ensures that all referenced script files are loaded |
|
notifyScriptLoaded |
Called by script files to notify the application object that the script has been successfully loaded |
|
queueScriptReference |
Queues a new script reference for loading |
|
removeComponent |
Removes the specified component from the page hierarchy |
Vents in the page lifetime
|
Event |
Description |
|---|---|
|
Init |
Occurs when the page is first initialized |
|
Load |
Occurs when the page is loaded |
|
loadTimedOut |
Occurs when the loading step takes too much time to complete |
|
scriptLoadFailed |
Occurs when one script fails to load for whatever reason |
|
Unload |
Occurs when the page is unloaded |
Create Custom ASP.NET AJAX Non-Visual Client Components
Components
- Derive from the component base class
- Typically have no UI representation, such as timer component that raise events at intervals but is not visible on the page.
- Have no associated DOM elements
- Encapsulate client code that is intended to be resuable across applications
Behavior
- Derive from the behavior base class, wich extend the Component base class
- Extend the behavior of DOM elements, such as a watermarking behavior of the DOM element that they are associated with.
- Can create UI elements, although they do not typically modified the basic of DOM element that they are associated with.
- If assigned an ID, can be accessed directly from the DOM element through a custom attribute( expando).
- Do not require an association with another client object, such as a class derived from the Control or Behavior classes.
- Can reference either a control or a non-control HTML element in their element property.
Controls
- Derive from the Control base class, which extends the Component base class.
- Represent a DOM element as a client object, typically changing the original DOM element's ordinary behavior to provide new functionality. For example, a menu control might read >li< items from a >ul< element as its source data, but not display a bulleted list.
- Are accessed from the DOM element directly through the control expando
Please refer this artical, in summary you need to do the following thing
- You need to create an component in js file
- add reference to the js file
- create the component instance in the application load event, the instance will be associated with other element in the page because the information is passed in the creation method.
Type.registerNamespace("Demo");
Demo.Timer = function() {
Demo.Timer.initializeBase(this);
this._interval = 1000;
this._enabled = false;
this._timer = null;}
Demo.Timer.prototype = {
// OK to declare value types in the prototype
get_interval: function() {
/// Interval in milliseconds
return this._interval; },
set_interval: function(value) {
if (this._interval !== value) {
this._interval = value;
this.raisePropertyChanged('interval');
if (!this.get_isUpdating() && (this._timer !== null))
{
this._restartTimer();
} } },
get_enabled: function() {
/// True if timer is enabled, false if disabled.
return this._enabled; },
set_enabled: function(value) {
if (value !== this.get_enabled()) {
this._enabled = value;
this.raisePropertyChanged('enabled');
if (!this.get_isUpdating())
{
if (value) {
this._startTimer(); } else {
this._stopTimer(); } } }
}, // events add_tick: function(handler) {
/// Adds a event handler for the tick event.
/// The handler to add to the event.
this.get_events().addHandler("tick", handler); },
remove_tick: function(handler) {
/// Removes a event handler for the tick event.
/// The handler to remove from the event.
this.get_events().removeHandler("tick", handler); },
dispose: function() {
// call set_enabled so the property changed event fires, for potentially attached listeners.
this.set_enabled(false);
// make sure it stopped so we aren't called after disposal
this._stopTimer(); // be sure to call base.dispose()
Demo.Timer.callBaseMethod(this, 'dispose'); },
updated: function() { Demo.Timer.callBaseMethod(this, 'updated');
// called after batch updates, this.beginUpdate(), this.endUpdate().
if (this._enabled) { this._restartTimer(); } },
_timerCallback: function() {
var handler = this.get_events().getHandler("tick");
if (handler) { handler(this, Sys.EventArgs.Empty); }
}, _restartTimer: function() { this._stopTimer();
this._startTimer(); }, _startTimer: function() {
// save timer cookie for removal later
this._timer = window.setInterval(Function.createDelegate(this, this._timerCallback), this._interval);
}, _stopTimer: function() { if(this._timer) {
window.clearInterval(this._timer); this._timer = null;
} }}
// JSON object that describes all properties, events, and methods of this component that should
// be addressable through the Sys.TypeDescriptor methods, and addressable via xml-script.
Demo.Timer.descriptor = { properties: [ {name: 'interval', type: Number},
{name: 'enabled', type: Boolean} ],
events: [ {name: 'tick'} ]}
Demo.Timer.registerClass('Demo.Timer', Sys.Component);
// Since this script is not loaded by System.Web.Handlers.ScriptResourceHandler
// invoke Sys.Application.notifyScriptLoaded to notify ScriptManager
// that this is the end of the script.
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
ASP.NET AJAX Life Cycle
- Sys.Application.init(event handle need Sys.Application.add_init(MyInit);
- Sys.Application.load (event handler function pageLoad(sender, args){}
- Sys.Application.unload (event handler function pageUnLoad(sender, args){}
- Sys.Application.disposing( inherit from Component class)
- Sys.Application.propertyChanged( inherit from Component class)
- Sys.WebForms.PageRequestManager.initializeRequest
- Sys.WebForms.PageRequestManager.beginRequest
- Sys.WebForms.PageRequestManager.pageLoading
- Sys.WebForms.PageRequestManager.pageLoaded
- Sys.WebForms.PageRequestManager.endRequest
For detail see this
Sys.Application.add_init(applicationInit);
//Sys.Application.add_load(applicationLoad);
Sys.Application.add_unload(applicationUnload);
function applicationInit(sender, args)
{
alert("application init");
}
function pageLoad(sender, args) {
//function applicationLoad(sender, args) {
alert("application load");
}
function applicationUnload(sender, args)
{
alert("application unload");
}
Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(pageRequestInitRequestHandler);
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(pageRequestManagerBeginRequestHandler);
Sys.WebForms.PageRequestManager.getInstance().add_pageLoading(pageReqeustPageLoading);
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(pageRequestManagerEndRequestHandler);
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageRequestManagerLoadHandler);
function pageRequestInitRequestHandler(sender, args)
{
alert("PageRequestManager initRequest");
}
function pageReqeustPageLoading(sender, args)
{
alert("PageRequestManager pageLoading");
}
function pageRequestManagerBeginRequestHandler(sender, args)
{
alert("PageRequestManager beginRequestr");
}
function pageRequestManagerLoadHandler(sender, args)
{
alert("PageRequestManager pageLoaded");
}
function pageRequestManagerEndRequestHandler(sender, args)
{
alert("PageRequestManager endRequest");
}
For the initial load, the event sequence is PageRequestManager pageLoaded, application init, application load. For asynchronous call, is PageRequestManager initRequest, PageRequestManager beginRequest, PageRequestManager pageLoading, PageRequestManager pageLoaded, application load, PageRequestManager endRequest.
ASP.NET AJAX WebRequest
// Instantiate a WebRequest.
var wRequest = new Sys.Net.WebRequest();
// Set the request URL.
wRequest.set_url("getTarget.htm");
// Set the request verb.
wRequest.set_httpVerb("GET");
// Set the request callback function.
wRequest.add_completed(OnWebRequestCompleted);
// Execute the request.
wRequest.invoke();
// This callback function processes the
// request return values. It is called asynchronously
// by the current executor.
function OnWebRequestCompleted(executor, eventArgs)
{
if(executor.get_responseAvailable())
{
// Clear the previous results.
resultElement.innerHTML = "";
// Display Web request status.
resultElement.innerHTML +=
"Status: [" + executor.get_statusCode() + " " +
executor.get_statusText() + "]" + "
";
// Display Web request headers.
resultElement.innerHTML +=
"Headers: ";
resultElement.innerHTML +=
executor.getAllResponseHeaders() + "
";
// Display Web request body.
resultElement.innerHTML +=
"Body:";
if(document.all)
resultElement.innerText +=
executor.get_responseData();
else
resultElement.textContent +=
executor.get_responseData();
}
}