- Do not use too many fonts on one page.
- Do not use centered, right, or full-justified text on a web page
- Give your text room to breath.
- Do not use bold type for paragraph text.
- Never, never, never use all capitalized text.
- Use plenty headlines and subheads
- Divide your page into columns
- Don't use huge text.
- Do not use underlined text for anything but a link.
- For graphic text, learn correct typography.
Aug 27, 2007
Ten Step to professional web type
Sharepoint Area
Area a like top level site. Topic, news, sites are three area created by default. They share the same feature that area has. An area has three default components(portal lists, document library, and image library). Topic has shortcut to create subarea. Topic area does not use any of this component. News use portal lists to add news. Sites area does not use default component. Instead it add one more custom lists(the name is Sites). Sites area has a shortcut to create site, in the process of site creation, you can add the short cut this site. This shortcut is actually an record in the "Sites" custome list. The root area is home. Topic, news, sites area are all
Why jQuery works
Its fundamental philosophy, centering on collections of DOM Elements, puts it squarely where most Javascript developers program most. By contrast, other frameworks, like Prototype and Dojo, take a functional approach. Sure, they’re fully capable of addressing DOM Elements, just like jQuery, but these other frameworks make entirely different choices. Prototype, for one, fancies itself a true Object Oriented extension of Javascript’s paltry native offerings. In pursuit of true object-orientedness, its developers have put a substantial amount of time into developing object-oriented classes for different types of functionality. A class for forms, a class for elements, a class for events. It goes on and on. It’s perfectly possible to write clean, good-looking Prototype code. And Prototype can emulate one of the best things about jQuery’s focus on DOM Element collections: its chainability. But jQuery conceives of modern Javascript development the way many major players in the Javascript community are starting to see it: as DOM Scripting first and foremost. For those of us whose Javascriptprogramming focuses primarily on page elements, and Isuspect that’s most of us, jQuery makes the work dead simple.
Most jQuery methods start with the collection of elements, using the handy support for CSS3, XPath, and a slew of custom expressions (like :visible, which returns only visible elements, and :checked, which returns only checked form fields). Once you obtain a group of elements, the fun begins. Add .fadeIn(“slow”) and each of the elements will fade in—slowly. But we’re not done. Without skipping a beat, add .addClass(“thisIsDamnFun”). Each element will get the class “thisIsDamnFun.” It is, isn’t it? And it can go on from there. Add .click(function() { alert(“Hello”) }); to throw up an alert box when any of the elements are clicked. Add .append(“Hello”) and the word hello will be appended to the end of each of the matched elements. Cool, huh?
Now that you’ve seen the power of jQuery methods, how do we get the element collection in the first place? Happily, we have CSS (1-3) at our disposal, as well as a limited subset of XPath, and some nice custom expressions thrown in for good measure. When I say CSS3, I mean it. jQuery supports the ~ selector, :not(expr), attributes via [@ attr=’whatever’]. XPath support is a bit more limited, but most of the good stuff is here. The / and // operators are available, as are parent and preceding sibling axes. jQuery supports :first, :last, and :eq(n), a slimmed down version of [position() = n]. Finally, jQuery supports testing for contained elements via [tag- Name]. And because the jQuery parses operates on XHTML, it can be easily co-opted for parsing raw XML from AJAX requests. And of course, jQuery has the full complement of AJAX methods through $.ajax, and $().load.
cross-site group
We don't need magic.
dbcc freeprocecache
AJAX basic
var xmlHttp = null;
if (window.XMLHttpRequest) { // IE7, Mozilla, Safari, Opera, etc.
xmlHttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {
try{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); //IE 5.x, 6
}
catch(e) {}
}
function sendRequest(url) {
if (xmlHttp) {
xmlHttp.open("GET", url, true); // true = async
xmlHttp.onreadystatechange = onCallback;
xmlHttp.setRequestHeader('Content-type',
'application/x-www-form-urlencoded');
xmlHttp.send(null);
}
}
function onCallback() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200){
var r = document.getElementById('results');
r.innerHTML = xmlHttp.responseText;
}
else {
alert('Error: ' + xmlHttp.status);
}
}
}
Investigate your SQL's compilation
SET NOCOUNT ON;
USE Northwind; -- use your database name here
DBCC FREEPROCCACHE; -- empty the procedure cache
GO
-- we will use tempdb..OptStats table to capture
-- the information from several executions
-- of sys.dm_exec_query_optimizer_info
IF (OBJECT_ID('tempdb..OptStats') IS NOT NULL)
DROP TABLE tempdb..OptStats;
GO
-- the purpose of this statement is
-- to create the temporary table tempdb..OptStats
SELECT 0 AS Run, *
INTO tempdb..OptStats
FROM sys.dm_exec_query_optimizer_info;
GO
-- this will populate the procedure cache
-- with this statement's plan so that it will not
-- generate any optimizer events when executed
-- next time
-- the following GO is intentional to ensure
-- the query plan reuse will happen for the following
-- INSERT for its next invocation in this script
GO
INSERT INTO tempdb..OptStats
SELECT 1 AS Run, *
FROM sys.dm_exec_query_optimizer_info;
GO
-- same reason as above; observe the "2" replaced "1"
-- therefore we will have different plan
GO
INSERT INTO tempdb..OptStats
SELECT 2 AS Run, *
FROM sys.dm_exec_query_optimizer_info;
GO
-- empty the temporary table
TRUNCATE TABLE tempdb..OptStats
GO
-- store the "before run" information
-- in the temporary table with the output
-- of sys.dm_exec_query_optimizer_info
-- with value "1" in the column Run
GO
INSERT INTO tempdb..OptStats
SELECT 1 AS Run, *
FROM sys.dm_exec_query_optimizer_info;
GO
-- your statement or batch is executed here
/*** the following is an example
SELECT C.CustomerID, COUNT(O.OrderID) AS NumOrders
FROM dbo.Customers AS C
LEFT OUTER JOIN dbo.Orders AS O
ON C.CustomerID = O.CustomerID
WHERE C.City = 'London'
GROUP BY C.CustomerID
HAVING COUNT(O.OrderID) > 5
ORDER BY NumOrders;
***/
GO
-- store the "after run" information
-- in the temporary table with the output
-- of sys.dm_exec_query_optimizer_info
-- with value "2" in the column Run
GO
INSERT INTO tempdb..OptStats
SELECT 2 AS Run, *
FROM sys.dm_exec_query_optimizer_info;
GO
-- extract all "events" that changed either
-- the Occurrence or Value column value between
-- the Runs 1 and 2 from the temporary table.
-- Display the values of Occurrence and Value
-- for all such events before (Run1Occurrence and
-- Run1Value) and after (Run2Occurrence and
-- Run2Value) executing your batch or query.
-- This is the result set generated by the script.
WITH X (Run,Counter, Occurrence, Value)
AS
(
SELECT *
FROM tempdb..OptStats WHERE Run=1
),
Y (Run,Counter, Occurrence, Value)
AS
(
SELECT *
FROM tempdb..OptStats
WHERE Run=2
)
SELECT X.Counter, Y.Occurrence-X.Occurrence AS Occurrence,
CASE (Y.Occurrence-X.Occurrence)
WHEN 0 THEN (Y.Value*Y.Occurrence-X.Value*X.Occurrence)
ELSE (Y.Value*Y.Occurrence-X.Value*X.Occurrence)/(Y.Occurrence-X.Occurrence)
END AS Value
FROM X JOIN Y
ON (X.Counter=Y.Counter
AND (X.Occurrence<>Y.Occurrence OR X.Value<>Y.Value));
GO
-- drop the temporary table
DROP TABLE tempdb..OptStats;
GO
sys.application
Providing a centralized place to execute the client code—This goal is reached by defining a custom page lifecycle on the client. As you’ll see in a moment, the client page lifecycle starts when the browser loads the page and ends when the user navigates away from the page or the page is reloaded. When each stage in the lifecycle is entered, the Application object raises a corresponding event.
Hosting the client components instantiated in the page—Once instantiated, client components become children of the Application object and can be easily accessed through the Application object. Also, they’re automatically disposed by the Application object when the web page is unloaded by the browser.
The primary tenet behind components is code reusability. Components implement a well-defined set of interfaces that allows them to interact with other components and to be interchanged between applications. Thanks to the base interfaces, the code encapsulated by components can change at any time without affecting the other processing logic.
The Microsoft Ajax Library provides specialized client classes that simplify the authoring of client components. The group of classes related to component development is called the client component model and closely mirrors the model in use in the .NET framework. In this way, you can write component-oriented client applications using JavaScript code.
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 26, 2007
Inline box
style, currentStyle, runtimeStyle
style reprensent the style attribute of an object. But think of it as javascript object. If an element has no style attribute defined, element.color will be undefined. currentStyle is IE object that attached to an element. In firefox it is not accessible.It is a read only object, so you can get the style no matter how the style is created(either from css style sheet or the style attribute of the object.) runtimeStyle is also IE proprietary object, it is meant to be used for write
function getStyle(elem, name)
{
if (elem.style[name])
{
return elem.style[name];
}
else if (elem.currentStyle)
{
return elem.currentStyle[name];
}
else if (document.defaultView && document.defaultView.getComputedStyle)
{
name = name.replace(/([A-Z])/g,"-$1");
name = name.toLowerCase();
var s = document.defaultView.getComputedStyle(elem,"");
return s && s.getPropertyValue(name);
}
else
{
return null;
}
}
A CUSTOM TOOPTIPS
function showTip(oEvent)
{
var oDiv = document.getElementById(“divTip1”);
oDiv.style.visibility = “visible”;
oDiv.style.left = oEvent.clientX + 5;
oDiv.style.top = oEvent.clientY + 5;
}
Aug 24, 2007
floating setting affected by the structure
We all want to express our document in a semantic way, but some time the structure of the document does affect the css. For example,
...
If we change the structure of the document, we put nav beind content, we need to do more styling. And it is not straight forward. like you need to float both element, and you need to use negative margin for the nav item. I think the performance is slower. The only questionable benifit, it put more emphasis on the content element.
Aug 22, 2007
Reference assembly generated in asp.net code file
<%@ Register TagPrefix="msdn" Namespace="MsdnMag" Assembly="__code" %>
This is the way that asp.net referring to an autocompiled assembly.Powered by ScribeFire.
Aug 21, 2007
tagMapping in asp.net
Aug 18, 2007
xslt parameter
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:param name="Age" ></xsl:param> <xsl:template match="/"> <html> <body> <xsl:value-of select="$Age"/> </body> </html> </xsl:template> </xsl:stylesheet>
XmlTextWriter xmlwriter = new XmlTextWriter(writer);
XsltArgumentList list = new XsltArgumentList();
list.AddParam("Age", "", "108");
xslt.Transform(doc, list, xmlwriter);
Parameter of a template
<xsl:apply-templates select="$castList" mode="DisplayToggle">
<xsl:with-param name="divID" select="$programID" />
</xsl:apply-templates>
<xsl:template match="CastList"
Basically parameter can be used variable, and constructed as variable. The difference is used with template. The "xsl:with-param" element is optional, if it is not defined, the default value of "xsl:param" will be used.
<xsl:apply-templates select="$orderRow"> <xsl:with-param name="sn1" select="1" /> </xsl:apply-templates> <xsl:template match="Row"> <xsl:param name="sn" select="2"></xsl:param> <xsl:param name="sn1" select="$sn"></xsl:param>
xslt variable
You can build a variable by using select like below.
Or you can build a variable using constructor like below
This is demo
If a variable initialized by a select course, it contains a set of nodes. You can use the variable as a node. For example,
If you are using constructor to build a constructor, the variable can hold any arbitrary content, this content is called result tree fragment. You can imagine a result tree fragment (RTF) as a fragment or a chunk of XML code. You can assign a result tree fragment to a variable directly, or result tree fragment can arise from applying templates or other XSLT instructions. The following code assigns a simple fragment of XML to the variable $author.
Jirka
Kosek
jirka@kosek.cz
Now let's say we want to extract the e-mail address from the $author variable. The most obvious way is to use an expression such as $author/email. But this will fail, as you can't apply XPath navigation to a variable of the type "result tree fragment."
...
...
If you want to reuse the content of result tree, you can put copy-of statement to where you want your output to be.
Save the transform result in a variable for reuse
<xsl:variable name="orderMarkup">
<xsl:apply-templates select="/Customer/Order" />
xsl:variable>
To reuse the markup
<xsl:template match="/">
<html>
<body>
<xsl:copy-of select="$ordercopy" />
body>
html>
xsl:template>
Xslt variable(node set)
<xsl:variable name ="persons" select="/all/persons/p" />
<xsl:variable name ="persons1">
<xsl:copy-of select="/all/persons/p"/>
xsl:variable>
The difference between them is that persons has parent, but persons1 has not parent because it is a deep copy.
xslt variable inmutable
position() function, count nodes with the count() function, sum their values with the sum() function, average
them with the avg() function, and get their minimum or maximum with the min() or max() functions.
Powered by ScribeFire.
Aug 16, 2007
SqlDateTime Limit
Powered by ScribeFire.
Aug 12, 2007
Animation in jQuery
jQuery provide an function "animate", it can be extended to add your custom animation.
animate(params, speed, easing, callback)
- params (Hash): A set of style attributes that you wish to animate, and to what end.
- speed (String|Number): (optional) A string representing one of the three predefined speeds ("slow", "normal", or "fast") or the number of milliseconds to run the animation (e.g. 1000).
- easing (String): (optional) The name of the easing effect that you want to use, out of box there are two values "linear" and "swing" (Plugin Required).
- callback (Function): (optional) A function to be executed whenever the animation completes, executes once for each element animated against.
easing: {
linear: function( p, n, firstNum, diff ) {
return firstNum + diff * p;
},
swing: function( p, n, firstNum, diff ) {
return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
}
},
All the build in animate is based on this function
The key aspect of this function is the object of style properties that will be animated, and to what end. Each key within the object represents a style property that will also be animated (for example: "height", "top", or "opacity").
Note that properties should be specified using camel case eg. marginLeft instead of margin-left.
The value associated with the key represents to what end the property will be animated. If a number is provided as the value, then the style property will be transitioned from its current state to that new number. Otherwise if the string "hide", "show", or "toggle" is provided, a default animation will be constructed for that property.
.
Aug 11, 2007
Some handy feature in jQuery
attr( key, fn )
Sets title attribute from src attribute.
$("img").attr("title", function() { return this.src });
toggleClass( class )
$("p").toggleClass("selected")
Before
Hello Hello Again
After
Hello Hello Again[
get()
return an array that contains in jQuery object
get( num )
return an
html(), text() and val()
html(val), text(val) and val(val)
end()
Revert the most recent 'destructive' operation, changing the set of matched elements to its previous state (right before the destructive operation).
If there was no destructive operation before, an empty set is returned.
A 'destructive' operation is any operation that changes the set of matched jQuery elements. These functions are: add, children, clone, filter, find, not, next, parent, parents, prev and siblings.
innerHTML, outHTML, innerText, outText
However, innerHTML is not w3c standard. But using it is much faster than standard dom manipualation.
jQuery Selector
CSS Selectors
- * any element
- E an element of type E
- E:nth-child(n) an E element, the n-th child of its parent
- E:first-child an E element, first child of its parent
- E:last-child an E element, last child of its parent
- E:only-child an E element, only child of its parent
- E:empty an E element that has no children (including text nodes)
- E:enabled a user interface element E which is not disabled
- E:disabled a user interface element E which is disabled
- E:checked a user interface element E which is checked (for instance a radio-button or checkbox)
- E:selected a user interface element E which is selected (one or more option elements inside a select) - not in the CSS spec, but nonetheless supported by jQuery
- E.warning an E element whose class is "warning"
- E#myid an E element with ID equal to "myid". (Will only match, at most, one element.)
- E:not(s) an E element that does not match simple selector s
- E F an F element descendant of an E element
- E > F an F element child of an E element
- E + F an F element immediately preceded by an E element
- E ~ F an F element preceded by an E element
- E,F,G select all E elements, F elements, and G elements
- E[@foo] an E element with a "foo" attribute
- E[@foo=bar] an E element whose "foo" attribute value is exactly equal to "bar"
- E[@foo^=bar] an E element whose "foo" attribute value begins exactly with the string "bar"
- E[@foo$=bar] an E element whose "foo" attribute value ends exactly with the string "bar"
- E[@foo*=bar] an E element whose "foo" attribute value contains the substring "bar"
XPath Selectors
Location Paths
- Relative to the entire HTML document
$("/html/body//p")
$("body//p")
$("p/../div")
- Relative to the context node this
$("p/*", this)
$("/p//a", this)
[edit]
- Descendant Element has a descendant element
$("//div//p")
- Child Element has a child element
$("//div/p")
- Preceding Sibling Element has an element before it, on the same axes
$("//div ~ form")
- Parent Selects the parent element of the element
$("//div/../p")
[edit]
- [@foo] Has an attribute of foo
$("//input[@checked]")
- [@foo='test'] Attribute foo is equal to test
$("//a[@ref='nofollow']")
- [Nodelist] Element contains a node list, for example:
$("//div[p]")
$("//div[p/a]")
[edit]
Supported Predicates, but differently
- [last()] or [position()=last()] becomes :last
$("p:last")
- [0] or [position()=0] becomes :eq(0) or :first
$("p:first")
$("p:eq(0)")
- [position() < 5] becomes :lt(5)
$("p:lt(5)")
- [position() > 2] becomes :gt(2)
$("p:gt(2)")
Custom Selectors
- :even Selects every other (even) element from the matched element set.
- :odd Selects every other (odd) element from the matched element set.
- :eq(0) and :nth(0) Selects the Nth element from the matched element set
- :gt(N) Selects all matched elements whose index is greater than N.
- :lt(N) Selects all matched elements whose index is less than N.
- :first Equivalent to :eq(0)
- :last Selects the last matched element.
- :parent Selects all elements which have child elements (including text).
- :contains('test') Selects all elements which contain the specified text.
- :visible Selects all visible elements (this includes items that have a display of block or inline, a visibility of visible, and aren't form elements of type hidden)
- :hidden Selects all hidden elements (this includes items that have a display of none, or a visibility of hidden, or are form elements of type hidden)
Some examples:
$("p:first").css("fontWeight","bold");
$("div:hidden").show();
$("/div:contains('test')", this).hide();
Form Selectors
There are a few selectors for form elements:
- :input Selects all form elements (input, select, textarea, button).
- :text Selects all text fields (type="text").
- :password Selects all password fields (type="password").
- :radio Selects all radio fields (type="radio").
- :checkbox Selects all checkbox fields (type="checkbox").
- :submit Selects all submit buttons (type="submit").
- :image Selects all form images (type="image").
- :reset Selects all reset buttons (type="reset").
- :button Selects all other buttons (type="button").
- :file Selects all .
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 9, 2007
to be small
Any fool can make things bigger, more complex, and more violent. It takes a touch of genius — and a lot of courage — to move in the opposite direction. ---Albert Einstein
Handling ajax exception
First you need to add an handler to the event OnAsyncPostBackError of scriptmanager
protected void AsyncPostBackError(object sender, AsyncPostBackErrorEventArgs e)
{
ScriptManager1.AsyncPostBackErrorMessage = "An error occurred and its description is:\n" +
e.Exception.Message;
}
In the page, you add this script
function pageLoad()
{
// Register handlers for UpdatePanel client events
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);
}
function endRequest(sender, args)
{
var err = args.get_error();
if (err != null)
{
$get("Label1").innerHTML = args.get_error().message;
args.set_errorHandled(true);
}
}
Add update panel dynamically
private Label Label1;
protected void Page_Load(object sender, EventArgs e)
{
UpdatePanel up1 = new UpdatePanel();
up1.ID = "UpdatePanel1";
// Define the button
Button button1 = new Button();
button1.ID = "Button1";
button1.Text = "What time is it?";
button1.Click += new EventHandler(Button1_Click);
// Define the literals
LiteralControl lit = new LiteralControl("
");
// Define the label
Label1 = new Label();
Label1.ID = "Label1";
Label1.Text = "[time]";
// Link controls to the UpdatePanel
up1.ContentTemplateContainer.Controls.Add(button1);
up1.ContentTemplateContainer.Controls.Add(lit);
up1.ContentTemplateContainer.Controls.Add(Label1);
// Add the UpdatePanel to the list
this.Form.Controls.Add(up1);
}
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = DateTime.Now.ToShortTimeString();
}
UpdatePanel load user control
string ascx = "customerview.ascx";
UpdatePanel1.ContentTemplate = this.LoadTemplate(ascx);
Aug 8, 2007
why set body margin to 0
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 6, 2007
Creating Custom ASP.NET AJAX Client Controls
- You need to write a js file to define the control
- You need to write script in the page the hookup the relation ship
Here is the js file
Type.registerNamespace("Demo");
// Constructor
Demo.HoverButton = function(element) {
Demo.HoverButton.initializeBase(this, [element]);
this._clickDelegate = null;
this._hoverDelegate = null;
this._unhoverDelegate = null;
}
Demo.HoverButton.prototype = {
// text property accessors.
get_text: function() {
return this.get_element().innerHTML;
},
set_text: function(value) {
this.get_element().innerHTML = value;
},
// Bind and unbind to click event.
add_click: function(handler) {
this.get_events().addHandler('click', handler);
},
remove_click: function(handler) {
this.get_events().removeHandler('click', handler);
},
// Bind and unbind to hover event.
add_hover: function(handler) {
this.get_events().addHandler('hover', handler);
},
remove_hover: function(handler) {
this.get_events().removeHandler('hover', handler);
},
// Bind and unbind to unhover event.
add_unhover: function(handler) {
this.get_events().addHandler('unhover', handler);
},
remove_unhover: function(handler) {
this.get_events().removeHandler('unhover', handler);
},
// Release resources before control is disposed.
dispose: function() {
var element = this.get_element();
if (this._clickDelegate) {
Sys.UI.DomEvent.removeHandler(element, 'click', this._clickDelegate);
delete this._clickDelegate;
}
if (this._hoverDelegate) {
Sys.UI.DomEvent.removeHandler(element, 'focus', this._hoverDelegate);
Sys.UI.DomEvent.removeHandler(element, 'mouseover', this._hoverDelegate);
delete this._hoverDelegate;
}
if (this._unhoverDelegate) {
Sys.UI.DomEvent.removeHandler(element, 'blur', this._unhoverDelegate);
Sys.UI.DomEvent.removeHandler(element, 'mouseout', this._unhoverDelegate);
delete this._unhoverDelegate;
}
Demo.HoverButton.callBaseMethod(this, 'dispose');
},
initialize: function() {
var element = this.get_element();
if (!element.tabIndex) element.tabIndex = 0;
if (this._clickDelegate === null) {
this._clickDelegate = Function.createDelegate(this, this._clickHandler);
}
Sys.UI.DomEvent.addHandler(element, 'click', this._clickDelegate);
if (this._hoverDelegate === null) {
this._hoverDelegate = Function.createDelegate(this, this._hoverHandler);
}
Sys.UI.DomEvent.addHandler(element, 'mouseover', this._hoverDelegate);
Sys.UI.DomEvent.addHandler(element, 'focus', this._hoverDelegate);
if (this._unhoverDelegate === null) {
this._unhoverDelegate = Function.createDelegate(this, this._unhoverHandler);
}
Sys.UI.DomEvent.addHandler(element, 'mouseout', this._unhoverDelegate);
Sys.UI.DomEvent.addHandler(element, 'blur', this._unhoverDelegate);
Demo.HoverButton.callBaseMethod(this, 'initialize');
},
_clickHandler: function(event) {
var h = this.get_events().getHandler('click');
if (h) h(this, Sys.EventArgs.Empty);
},
_hoverHandler: function(event) {
var h = this.get_events().getHandler('hover');
if (h) h(this, Sys.EventArgs.Empty);
},
_unhoverHandler: function(event) {
var h = this.get_events().getHandler('unhover');
if (h) h(this, Sys.EventArgs.Empty);
}
}
Demo.HoverButton.registerClass('Demo.HoverButton', Sys.UI.Control);
// 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();
Here the hookup code
var app = Sys.Application;
app.add_load(applicationLoadHandler);
function applicationLoadHandler(sender, args) {
$create(
Demo.HoverButton, //The component type.
{text: 'A HoverButton Control',element: {style: {fontWeight: "bold", borderWidth: "2px"}}}, //A JSON object that contains a component ID value and optionally any initial property name/value pairs.
{click: start, hover: doSomethingOnHover, unhover: doSomethingOnUnHover}, //An optional JSON object that contains event name and event/handler binding pairs.
null, //An optional JSON object that contains references to associated components, passed as component name/ID pairs.
$get('Button1') //clientside control
);
}
function doSomethingOnHover(sender, args) {
hoverMessage = "The mouse is over the button."
$get('HoverLabel').innerHTML = hoverMessage;
}
function doSomethingOnUnHover(sender, args) {
$get('HoverLabel').innerHTML = "";
}
function start(sender, args) {
alert("The start function handled the HoverButton click event.");
}
Adding Client Behaviors to Web Server Controls by Using ASP.NET AJAX Extensions
A behavior adds functionality to client Document Object Model (DOM) elements. The client behavior can be encapsulated in a Web server control as an extender control. The extender control is then associated with one or more types of ASP.NET server controls to add the behavior to those server controls. You can associate more than one extender control with an ASP.NET server control. An extender control is a web server control that inherites the ExtenderControl. GetScriptDescripters returns a collection of ScriptDescriptor objects that contain information about instances of client components that are used with web server control. This includes the client type to create, the properties to assign, and the events to add handlers for. See the script example below, they will be generated according to this information. GetScriptReferences() returns a collection of ScriptReference objects that contains information about the client-script libraries to be include with then control. The client-script libraries define the client types and include any other javascript code that is required for the control.
protected override IEnumerable GetScriptDescriptors(Control targetControl)
{
ScriptBehaviorDescriptor descriptor = new ScriptBehaviorDescriptor("Samples.FocusBehavior", targetControl.ClientID);
descriptor.AddProperty("highlightCssClass", this.HighlightCssClass);
descriptor.AddProperty("nohighlightCssClass", this.NoHighlightCssClass);
return new ScriptDescriptor[] { descriptor };
}
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 = {};