diff options
Diffstat (limited to 'demos/quickstart/protected/pages/Advanced')
14 files changed, 1297 insertions, 54 deletions
diff --git a/demos/quickstart/protected/pages/Advanced/Assets.page b/demos/quickstart/protected/pages/Advanced/Assets.page index d69a1bcd..e79f4ecf 100644 --- a/demos/quickstart/protected/pages/Advanced/Assets.page +++ b/demos/quickstart/protected/pages/Advanced/Assets.page @@ -1,6 +1,6 @@ <com:TContent ID="body" >
-<h1>Assets</h1>
+<h1 id="5701">Assets</h1>
<p>
Assets are resource files (such as images, sounds, videos, CSS stylesheets, javascripts, etc.) that belong to specific component classes. Assets are meant to be provided to Web users. For better reusability and easier deployment of the corresponding component classes, assets should reside together with the component class files . For example, a toggle button may use two images, stored in file <tt>down.gif</tt> and <tt>up.gif</tt>, to show different toggle states. If we require the image files be stored under <tt>images</tt> directory under the Web server document root, it would be inconvenient for the users of the toggle button component, because each time they develop or deploy a new application, they would have to manually copy the image files to that specific directory. To eliminate this requirement, a directory relative to the component class file should be used for storing the image files. A common strategy is to use the directory containing the component class file to store the asset files.
</p>
@@ -8,7 +8,7 @@ Assets are resource files (such as images, sounds, videos, CSS stylesheets, java Because directories containing component class files are normally inaccessible by Web users, PRADO implements an asset publishing scheme to make available the assets to Web users. An asset, after being published, will have a URL by which Web users can retrieve the asset file.
</p>
-<h2>Asset Publishing</h2>
+<h2 id="5702">Asset Publishing</h2>
<p>
PRADO provides several methods for publishing assets or directories containing assets:
</p>
@@ -21,7 +21,7 @@ PRADO provides several methods for publishing assets or directories containing a BE AWARE: Be very careful with assets publishing, because it gives Web users access to files that were previously inaccessible to them. Make sure that you do not publish files that do not want Web users to see.
</p>
-<h2>Customization</h2>
+<h2 id="5703">Customization</h2>
<p>
Asset publishing is managed by the <tt>System.Web.TAssetManager</tt> module. By default, all published asset files are stored under the <tt>[AppEntryPath]/assets</tt> directory, where <tt>AppEntryPath</tt> refers to the directory containing the application entry script. Make sure the <tt>assets</tt> directory is writable by the Web server process. You may change this directory to another by configuring the <tt>BasePath</tt> and <tt>BaseUrl</tt> properties of the <tt>TAssetManager</tt> module in application configuration,
</p>
@@ -34,7 +34,7 @@ Asset publishing is managed by the <tt>System.Web.TAssetManager</tt> module. By </modules>
</com:TTextHighlighter>
-<h2>Performance</h2>
+<h2 id="5704">Performance</h2>
<p>
PRADO uses caching techniques to ensure the efficiency of asset publishing. Publishing an asset essentially requires file copy operation, which is expensive. To save unnecessary file copy operations, <tt>System.Web.TAssetManager</tt> only publishes an asset when it has a newer file modification time than the published file. When an application runs under the <tt>Performance</tt> mode, such timestamp checkings are also omitted.
</p>
@@ -42,7 +42,7 @@ PRADO uses caching techniques to ensure the efficiency of asset publishing. Publ ADVISORY: Do not overuse asset publishing. The asset concept is mainly used to help better reuse and redistribute component classes. Normally, you should not use asset publishing for resources that are not bound to any component in an application. For example, you should not use asset publishing for images that are mainly used as design elements (e.g. logos, background images, etc.) Let Web server to directly serve these images will help improve the performance of your application.
</p>
-<h2>A Toggle Button Example</h2>
+<h2 id="5705">A Toggle Button Example</h2>
<p>
We now use the toggle button example to explain the usage of assets. The control uses two image files <tt>up.gif</tt> and <tt>down.gif</tt>, which are stored under the directory containing the control class file. When the button is in <tt>Up</tt> state, we would like to show the <tt>up.gif</tt> image. This can be done as follows,
</p>
diff --git a/demos/quickstart/protected/pages/Advanced/Auth.page b/demos/quickstart/protected/pages/Advanced/Auth.page index ec876f54..3373644a 100644 --- a/demos/quickstart/protected/pages/Advanced/Auth.page +++ b/demos/quickstart/protected/pages/Advanced/Auth.page @@ -1,6 +1,6 @@ <com:TContent ID="body" >
-<h1>Authentication and Authorization</h1>
+<h1 id="5501">Authentication and Authorization</h1>
<p>
Authentication is a process of verifying whether someone is who he claims he is. It usually involves a username and a password, but may include any other methods of demonstrating identity, such as a smart card, fingerprints, etc.
</p>
@@ -8,7 +8,7 @@ Authentication is a process of verifying whether someone is who he claims he is. Authorization is finding out if the person, once identified, is permitted to manipulate specific resources. This is usually determined by finding out if that person is of a particular role that has access to the resources.
</p>
-<h2>How PRADO Auth Framework Works</h2>
+<h2 id="5502">How PRADO Auth Framework Works</h2>
<p>
PRADO provides an extensible authentication/authorization framework. As described in <a href="?page=Fundamentals.Applications">application lifecycles</a>, <tt>TApplication</tt> reserves several lifecycles for modules responsible for authentication and authorization. PRADO provides the <tt>TAuthManager</tt> module for such purposes. Developers can plug in their own auth modules easily. <tt>TAuthManager</tt> is designed to be used together with <tt>TUserManager</tt> module, which implements a read-only user database.
</p>
@@ -19,7 +19,7 @@ When a page request occurs, <tt>TAuthManager</tt> will try to restore user infor During <tt>Authorization</tt> application lifecycle, which occurs after <tt>Authentication</tt> lifecycle, <tt>TAuthManager</tt> will verify if the current user has access to the requested page according to a set of authorization rules. The authorization is role-based, i.e., a user has access to a page if 1) the page explicitly states that the user has access; 2) or the user is of a particular role that has access to the page. If the user does not have access to the page, <tt>TAuthManager</tt> will redirect user browser to the login page which is specified by <tt>LoginPage</tt> property.
</p>
-<h2>Using PRADO Auth Framework</h2>
+<h2 id="5503">Using PRADO Auth Framework</h2>
<p>
To enable PRADO auth framework, add the <tt>TAuthManager</tt> module and <tt>TUserManager</tt> module to <a href="?page=Configurations.AppConfig">application configuration</a>,
</p>
@@ -75,7 +75,7 @@ When a page request is being processed, a list of authorization rules may be ava In the above example, anonymous users will be denied from posting to <tt>PageID1</tt> and <tt>PageID2</tt>, while <tt>User1</tt> and <tt>User2</tt> and all users of role <tt>Role1</tt> can access the two pages (in both <tt>get</tt> and <tt>post</tt> methods).
</p>
-<h2>Using <tt>TUserManager</tt></h2>
+<h2 id="5504">Using <tt>TUserManager</tt></h2>
<p>
As aforementioned, <tt>TUserManager</tt> implements a read-only user database. The user information are specified in either application configuration or an external XML file.
</p>
diff --git a/demos/quickstart/protected/pages/Advanced/Error.page b/demos/quickstart/protected/pages/Advanced/Error.page index 55217bfe..9d5e3037 100644 --- a/demos/quickstart/protected/pages/Advanced/Error.page +++ b/demos/quickstart/protected/pages/Advanced/Error.page @@ -1,11 +1,11 @@ <com:TContent ID="body" >
-<h1>Error Handling and Reporting</h1>
+<h1 id="6301">Error Handling and Reporting</h1>
<p>
PRADO provides a complete error handling and reporting framework based on the PHP 5 exception mechanism.
</p>
-<h2>Exception Classes</h2>
+<h2 id="6302">Exception Classes</h2>
<p>
Errors occur in a PRADO application may be classified into three categories: those caused by PHP script parsing, those caused by wrong code (such as calling an undefined function, setting an unknown property), and those caused by improper use of the Web application by client users (such as attempting to access restricted pages). PRADO is unable to deal with the first category of errors because they cannot be caughted in PHP code. PRADO provides an exception hierarchy to deal with the second and third categories.
</p>
@@ -32,18 +32,18 @@ Exceptions raised due to improper usage of the PRADO framework inherit from <tt> Errors due to improper usage of the Web application by client users inherit from <tt>TApplicationException</tt>.
</p>
-<h2>Raising Exceptions</h2>
+<h2 id="6303">Raising Exceptions</h2>
<p>
Raising exceptions in PRADO has no difference than raising a normal PHP exception. The only thing matters is to raise the right exception. In general, exceptions meant to be shown to application users should use <tt>THttpException</tt>, while exceptions shown to developers should use other exception classes.
</p>
-<h2>Error Capturing and Reporting</h2>
+<h2 id="6304">Error Capturing and Reporting</h2>
<p>
Exceptions raised during the runtime of PRADO applications are captured by <tt>System.Exceptions.TErrorHandler</tt> module. Different output templates are used to display the captured exceptions. <tt>THttpException</tt> is assumed to contain error messages that are meant for application end users and thus uses a specific group of templates. For all other exceptions, a common template shown as follows is used for presenting the exceptions.
</p>
<a href="<%~ exception2.gif %>" target="_blank"><img src="<%~ exception.gif %>" alt="exception page" style="border:0px"/></a>
-<h2>Customizing Error Display</h2>
+<h2 id="6305">Customizing Error Display</h2>
<p>
Developers can customize the presentation of exception messages. By default, all error output templates are stored under <tt>framework/Exceptions/templates</tt>. The location can be changed by configuring <tt>TErrorHandler</tt> in application configuration,
</p>
diff --git a/demos/quickstart/protected/pages/Advanced/I18N.page b/demos/quickstart/protected/pages/Advanced/I18N.page index 4a220c4c..5b1fafa0 100644 --- a/demos/quickstart/protected/pages/Advanced/I18N.page +++ b/demos/quickstart/protected/pages/Advanced/I18N.page @@ -1,9 +1,9 @@ <com:TContent ID="body" >
-<h1>Internationalization (I18N) and Localization (L10N)</h1>
+<h1 id="6201">Internationalization (I18N) and Localization (L10N)</h1>
<p>Many web application built with PHP will not have internationalization in mind when it was first written. It may be that it was not intended for use in languages and cultures. Internationalization is an important aspect due to the increase adoption of the Internet in many non-English speaking countries. The process of internationalization and localization will contain difficulties. Below are some general guidelines to internationalize an existing application.</p>
-<h2>Separate culture/locale sensitive data</h2>
+<h2 id="6203">Separate culture/locale sensitive data</h2>
<p>Identify and separate data that varies with culture. The most obvious are text/string/message. Other type of data should also be considered. The following list categorize some examples of culture sensitive data
</p>
@@ -25,7 +25,7 @@ <p>If possible all manner of text should be isolated and store in a persistence format. These text include, application error messages, hard coded strings in PHP files, emails, static HTML text, and text on form elements (e.g. buttons).</p>
-<h2>Configuration</h2>
+<h2 id="6204">Configuration</h2>
<p>To enable the localization features in Prado, you need to add a few configuration options in your <a href="?page=Configurations.AppConfig">application configuration</a>.
First you need to include the <tt>System.I18N.*</tt> namespace to your paths.
</p>
@@ -52,7 +52,7 @@ With <tt>cache</tt> enabled, translated messages are saved in the application <t <p>With the configuration complete, we can now start to localize your application. If you have <tt>autosave</tt> enabled, after running your application with some localization activity (i.e. translating some text), you will see a directory and a <tt>messages.xml</tt> created within your <tt>source</tt> directory.</p>
-<h2>What to do with <tt>messages.xml</tt>?</h2>
+<h2 id="6205">What to do with <tt>messages.xml</tt>?</h2>
<p>The translation message catalogue file, if using <tt>type="XLIFF"</tt>, is a standardized translation message interchange XML format. You can edit the XML file using any UTF-8 aware editor. The format of the XML is something like the following.</p>
<com:TTextHighlighter Language="xml" CssClass="source">
@@ -77,7 +77,7 @@ With <tt>cache</tt> enabled, translated messages are saved in the application <t Each translation message is wrapped within a <tt>trans-unit</tt> tag, where <tt>source</tt> is the original message, and <tt>target</tt> is the translated message. Editors such as <a href="http://www.heartsome.net/EN/xlfedit.html">Heartsome XLIFF Translation Editor</a> can help in editing these XML files.
-<h2>Setting and Changing Culture</h2>
+<h2 id="6206">Setting and Changing Culture</h2>
<p>Once globalization is enabled, you can access the globalization settings, such as, <tt>Culture</tt>, <tt>Charset</tt>, etc, using </p>
<com:TTextHighlighter CssClass="source">
$globalization = $this->getApplication()->getGlobalization();
@@ -98,9 +98,9 @@ Lastly, you can change the globalization settings on page by page basis using <a <%@ Application.Globalization.Culture="zh" %>
</com:TTextHighlighter>
-<h2>Localizing your Prado application</h2>
+<h2 id="6207">Localizing your Prado application</h2>
There are two areas in your application that may need message or string localization, in PHP code and in the templates. To localize strings within PHP, use the <tt>localize</tt> function detailed below. To localize text in the template, use the <a href="#ttranslate">TTranslate</a> component.
-<h2>Using <tt>localize</tt> function to translate text within PHP</h2>
+<h2 id="6208">Using <tt>localize</tt> function to translate text within PHP</h2>
<p>The <tt>localize</tt> function searches for a translated string that matches original from your translation source. First, you need to locate all the hard coded text in PHP that are displayed or sent to the end user. The following example localizes the text of the <tt>$sender</tt> (assuming, say, the sender is a button). The original code before localization is as follows.
<com:TTextHighlighter CssClass="source">
@@ -118,7 +118,7 @@ function clickMe($sender,$param) }
</com:TTextHighlighter>
-<h2>Compound Messages</h2>
+<h2 id="6209">Compound Messages</h2>
<p>Compound messages can contain variable data. For example, in the message "There are 12 users online.", the integer 12 may change depending on some data in your application. This is difficult to translate because the position of the variable data may be difference for different languages. In addition, different languages have their own rules for plurals (if any) and/or quantifiers. The following example can not be easily translated, because the sentence structure is fixed by hard coding the variable data within message.</p>
<com:TTextHighlighter CssClass="source">
@@ -137,9 +137,9 @@ The <tt>localize</tt> function does not solve the problem of localizing language <p>The following sample demonstrates the basics of localization in Prado.</p>
<com:RunBar PagePath="Advanced.Samples.I18N.Home" />
-<h1>I18N Components</h1>
+<h1 id="6202">I18N Components</h1>
<a name="ttranslate"></a>
-<h2>TTranslate</h2>
+<h2 id="6210">TTranslate</h2>
<p>Messages and strings can be localized in PHP or in templates.
To translate a message or string in the template, use <tt>TTranslate</tt>.</p>
@@ -164,7 +164,7 @@ The time is {time}. <com:TLabel Text="<%[ Hello World! ]%>" />
</com:TTextHighlighter>
-<h2>TDateFormat</h2>
+<h2 id="6211">TDateFormat</h2>
<p>Formatting localized date and time is straight forward.</p>
<com:TTextHighlighter Language="prado" CssClass="source">
<com:TDateFormat Value="12/01/2005" />
@@ -254,7 +254,7 @@ Format Pattern Result <p>If the <tt>Value</tt> property is not specified, the current date and time is used.</p>
-<h2>TNumberFormat</h2>
+<h2 id="6212">TNumberFormat</h2>
<p>PRADO's Internationalization framework provide localized currency formatting and number formatting. Please note that the <tt>TNumberFormat</tt> component provides formatting only, it does not perform current conversion or exchange.</p>
<p>Numbers can be formatted as currency, percentage, decimal or scientific
@@ -310,7 +310,7 @@ Pattern Output </com:TTextHighlighter>
</p>
-<h2>TTranslateParameter</h2>
+<h2 id="6213">TTranslateParameter</h2>
<p>Compound messages, i.e., string substitution, can be accomplished with <tt>TTranslateParameter</tt>.
In the following example, the strings "{greeting}" and "{name}" will be replace
with the values of "Hello" and "World", respectively.The substitution string must be enclose with "{" and "}". The parameters can be further translated by using <tt>TTranslate</tt>.
@@ -325,7 +325,7 @@ with the values of "Hello" and "World", respectively.The substitution string mus <a name="choice-format"></a>
-<h2>TChoiceFormat</h2>
+<h2 id="6214">TChoiceFormat</h2>
<p>Using the <tt>localize</tt> function or <tt>TTranslate</tt> component to translate messages does not inform the translator the cardinality of the data required to determine the correct plural structure to use. It only informs them that there is a variable data, the data could be anything. Thus, the translator will be unable to determine with respect to the substitution data the correct plural, language structure or phrase to use . E.g. in English, to translate the sentence, "There are {number} of apples.", the resulting translation should be different depending on the <tt>number</tt> of apples.</p>
diff --git a/demos/quickstart/protected/pages/Advanced/Logging.page b/demos/quickstart/protected/pages/Advanced/Logging.page index ec3e7879..5270a00d 100644 --- a/demos/quickstart/protected/pages/Advanced/Logging.page +++ b/demos/quickstart/protected/pages/Advanced/Logging.page @@ -1,12 +1,12 @@ <com:TContent ID="body" >
-<h1>Logging</h1>
+<h1 id="6101">Logging</h1>
<p>
PRADO provides a highly flexible and extensible logging functionality. Messages logged can be classified according to log levels and message categories. Using level and category filters, the messages can be further routed to different destinations, such as files, emails, browser windows, etc. The following diagram shows the basic architecture of PRADO logging mechanism,
</p>
<img src="<%~ logrouter.gif %>" alt="Log router" />
-<h2>Using Logging Functions</h2>
+<h2 id="6102">Using Logging Functions</h2>
<p>
The following two methods are provided for logging messages in PRADO,
</p>
@@ -18,7 +18,7 @@ Prado::trace($message, $category); The difference between <tt>Prado::log()</tt> and <tt>Prado::trace()</tt> is that the latter automatically selects the log level according to the application mode. If the application is in <tt>Debug</tt> mode, stack trace information is appended to the messages. <tt>Prado::trace()</tt> is widely used in the core code of the PRADO framework.
</p>
-<h2>Message Routing</h2>
+<h2 id="6103">Message Routing</h2>
<p>
Messages logged using the above two functions are kept in memory. To make use of the messages, developers need to route them to specific destinations, such as files, emails, or browser windows. The message routing is managed by <tt>System.Util.TLogRouter</tt> module. When plugged into an application, it can route the messages to different destination in parallel. Currently, PRADO provides three types of routes:
</p>
@@ -44,7 +44,7 @@ To enable message routing, plug in and configure the <tt>TLogRouter</tt> module In the above, the <tt>Levels</tt> and <tt>Categories</tt> specify the log and category filters to selectively retrieve the messages to the corresponding destinations.
</p>
-<h2>Message Filtering</h2>
+<h2 id="6104">Message Filtering</h2>
<p>
Messages can be filtered according to their log levels and categories. Each log message is associated with a log level and a category. With levels and categories, developers can selectively retrieve messages that they are interested on.
</p>
diff --git a/demos/quickstart/protected/pages/Advanced/MasterContent.page b/demos/quickstart/protected/pages/Advanced/MasterContent.page index 0a68fe31..2698f865 100644 --- a/demos/quickstart/protected/pages/Advanced/MasterContent.page +++ b/demos/quickstart/protected/pages/Advanced/MasterContent.page @@ -1,6 +1,6 @@ <com:TContent ID="body" >
-<h1>Master and Content</h1>
+<h1 id="5801">Master and Content</h1>
<p>
Pages in a Web application often share common portions. For example, all pages of this tutorial application share the same header and footer portions. If we repeatedly put header and footer in every page source file, it will be a maintenance headache if in future we want to something in the header or footer. To solve this problem, PRADO introduces the concept of master and content. It is essentially a decorator pattern, with content being decorated by master.
</p>
diff --git a/demos/quickstart/protected/pages/Advanced/Performance.page b/demos/quickstart/protected/pages/Advanced/Performance.page index ed0cc6f8..d33c110b 100644 --- a/demos/quickstart/protected/pages/Advanced/Performance.page +++ b/demos/quickstart/protected/pages/Advanced/Performance.page @@ -1,11 +1,11 @@ <com:TContent ID="body" >
-<h1>Performance Tuning</h1>
+<h1 id="6401">Performance Tuning</h1>
<p>
Performance of Web applications is affected by many factors. Database access, file system operations, network bandwidth are all potential affecting factors. PRADO tries in every effort to reduce the performance impact caused by the framework.
</p>
-<h2>Caching</h2>
+<h2 id="6402">Caching</h2>
<p>
PRADO provides a generic caching technique used by in several core parts of the framework. For example, when caching is enabled, <tt>TTemplateManager</tt> will save parsed templates in cache and reuse them in the following requests, which saves time for parsing templates. The <tt>TThemeManager</tt> adopts the similar strategy to deal with theme parsing.
</p>
@@ -33,7 +33,7 @@ if($application->Cache) { where <tt>$keyName</tt> should be a string that uniquely identifies the data item stored in cache.
</p>
-<h2>Using <tt>pradolite.php</tt></h2>
+<h2 id="6403">Using <tt>pradolite.php</tt></h2>
<p>
Including many PHP script files may impact application performance significantly. PRADO classes are stored in different files and when processing a page request, it may require including tens of class files.To alleviate this problem, in each PRADO release, a file named <tt>pradolite.php</tt> is also included. The file is a merge of all core PRADO class files with comments being stripped off and message logging removed.
</p>
@@ -41,7 +41,7 @@ Including many PHP script files may impact application performance significantly To use <tt>pradolite.php</tt>, in your application entry script, replace the inclusion of <tt>prado.php</tt> with <tt>pradolite.php</tt>.
</p>
-<h2>Changing Application Mode</h2>
+<h2 id="6404">Changing Application Mode</h2>
<p>
Application mode also affects application performance. A PRADO application can be in one of the following modes: <tt>Off</tt>, <tt>Debug</tt>, <tt>Normal</tt> and <tt>Performance</tt>. The <tt>Debug</tt> mode should mainly be used during application development, while <tt>Normal</tt> mode is usually used in early stage after an application is deployed to ensure everything works correctly. After the application is proved to work stably for some period, the mode can be switched to <tt>Performance</tt> to further improve the performance.
</p>
@@ -57,7 +57,7 @@ To switch application mode, configure it in application configuration: </application >
</com:TTextHighlighter>
-<h2>Reducing Page Size</h2>
+<h2 id="6405">Reducing Page Size</h2>
<p>
By default, PRADO stores page state in hidden fields of the HTML output. The page state could be very large in size if complex controls, such as <tt>TDataGrid</tt>, is used. To reduce the size of the network transmitted page size, two strategies can be used.
</p>
@@ -76,7 +76,7 @@ Second, you may use a different page state storage. For example, page state may Note, in the above the <tt>SpecialPage</tt> will use <tt>MyPersister2</tt> as its persister class, while the rest pages will use <tt>MyPersister1</tt>. Therefore, you can have different state persister strategies for different pages.
</p>
-<h2>Other Techniques</h2>
+<h2 id="6406">Other Techniques</h2>
<p>
Server caching techniques are proven to be very effective in improving the performance of PRADO applications. For example, we have observed that by using Zend Optimizer, the RPS (request per second) of a PRADO application can be increased by more than ten times. Of course, this is at the cost of stale output, while PRADO's caching techniques always ensure the correctness of the output.
</p>
diff --git a/demos/quickstart/protected/pages/Advanced/Scripts.page b/demos/quickstart/protected/pages/Advanced/Scripts.page new file mode 100644 index 00000000..5921e865 --- /dev/null +++ b/demos/quickstart/protected/pages/Advanced/Scripts.page @@ -0,0 +1,397 @@ +<com:TContent ID="body" >
+<h1 id="6501">Introduction to Javascript</h1>
+This guide is based on the <a href="http://www.sergiopereira.com/articles/advjs.html">
+Quick guide to somewhat advanced JavaScript tour of some OO features</a> by Sergio Pereira.
+
+<h2 id="6502">Hey, I didn't know you could do that</h2>
+<p>
+ If you are a web developer and come from the same place I do, you have probably
+ used quite a bit of Javascript in your web pages, mostly as UI glue.
+</p>
+<p>
+
+ Until recently, I knew that Javascript had more OO capabilities than I was employing,
+ but I did not feel like I needed to use it. As the browsers started to support a more
+ standardized featureset of Javascript and the DOM, it became viable to write more
+ complex and functional code to run on the client. That helped giving birth to the
+ AJAX phenomena.
+</p>
+<p>
+ As we all start to learn what it takes to write our cool, AJAXy applications, we begin
+ to notice that the Javascript we used to know was really just the tip of the iceberg.
+ We now see Javascript being used beyond simple UI chores like input validation and frivolous
+ tasks. The client code now is far more advanced and layered, much like a real desktop
+ application or a client-server thick client. We see class libraries, object models,
+ hierarchies, patterns, and many other things we got used to seeing only in our server
+ side code.
+</p>
+<p>
+ In many ways we can say that suddenly the bar was put much higher than before. It takes
+ a heck lot more proficiency to write applications for the new Web and we need to improve
+ our Javascript skills to get there.
+ If you try to use many of the existing javascript libraries out there, like
+ <a href="http://prototype.conio.net/">Prototype.js</a>,
+ <a href="http://script.aculo.us/">Scriptaculous</a>,
+ <a href="http://moofx.mad4milk.net/">moo.fx</a>,
+ <a href="http://bennolan.com/behaviour/">Behaviour</a>,
+ <a href="http://developer.yahoo.net/yui/">YUI</a>,
+ etc you'll eventually find yourself reading the JS code. Maybe because you want
+ to learn how they do it, or because you're curious, or more often because that's the
+ only way to figure out how to use it, since documentation does not seem to be highly
+ regarded with most of these libraries. Whatever the case may be, you'll face some
+ kung-fu techniques that will be foreign and scary if you haven't seen anything like
+ that before.
+</p>
+
+<p>
+ The purpose of this article is precisely explaining the types of constructs that
+ many of us are not familiar with yet.
+</p>
+
+
+<h2 id="6503">JSON (JavaScript Object Notation)</h2>
+<p>
+ JavaScript Object Notation (<a href="http://www.json.org/">JSON</a>,) is one of the new
+ buzzwords popping up around the AJAX theme. JSON, simply put, is a way of
+ declaring an object in javascript. Let's see an example right away and note
+ how simple it is.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var myPet = { color: 'black', leg_count: 4, communicate: function(repeatCount){
+for(i=0;i<repeatCount;i++) alert('Woof!');} };
+</com:TTextHighlighter>
+
+<p>
+ Let's just add little bit of formatting so it looks more like how we usually find out there:
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var myPet =
+{
+ color: 'black',
+ legCount: 4,
+ communicate: function(repeatCount)
+ {
+ for(i=0;i<repeatCount;i++)
+ alert('Woof!');
+ }
+};
+</com:TTextHighlighter>
+<p>
+ Here we created a reference to an object with two properties (<tt>color</tt>
+ and <tt>legCount</tt>) and a method (<tt>communicate</tt>.)
+ It's not hard to figure out that the object's properties and methods
+ are defined as a comma delimited list. Each of the members is introduced by name, followed
+ by a colon and then the definition. In the case of the properties it is easy, just the value
+ of the property. The methods are created by assigning an anonymous function, which we will
+ explain better down the line.
+ After the object is created and assigned to the variable <tt>myPet</tt>,
+ we can use it like this:
+</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+alert('my pet is ' + myPet.color);
+alert('my pet has ' + myPet.legCount + ' legs');
+//if you are a dog, bark three times:
+myPet.communicate(3);
+</com:TTextHighlighter>
+<p>
+ You'll see JSON used pretty much everywhere in JS these days, as arguments to functions,
+ as return values, as server responses (in strings,) etc.
+</p>
+
+<h2 id="6504">What do you mean? A function is an object too?</h2>
+<p>
+ This might be unusual to developers that never thought about that, but in JS a function is
+ also an object. You can pass a function around as an argument to another function just like
+ you can pass a string, for example. This is extensively used and very handy.
+</p>
+
+<p>
+ Take a look at this example. We will pass functions to another function that will use them.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var myDog =
+{
+ bark: function()
+ {
+ alert('Woof!');
+ }
+};
+
+var myCat =
+{
+ meow: function()
+ {
+ alert('I am a lazy cat. I will not meow for you.');
+ }
+};
+
+function annoyThePet(petFunction)
+{
+ //let's see what the pet can do
+ petFunction();
+}
+
+//annoy the dog:
+annoyThePet(myDog.bark);
+//annoy the cat:
+annoyThePet(myCat.meow);
+</com:TTextHighlighter>
+<p>
+ Note that we pass myDog.bark and myCat.meow without appending parenthesis
+ <tt>"()"</tt> to them. If we did that we would not be passing
+ the function, rather we would be calling the method and passing the return value,
+ <tt>undefined</tt> in both cases here.
+</p>
+
+<p>
+ If you want to make my lazy cat start barking, you can easily do this:
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+myCat.meow = myDog.bark;
+myCat.meow(); //alerts 'Woof!'
+</com:TTextHighlighter>
+
+<h2 id="6505">Arrays, items, and object members</h2>
+<p>
+ The following two lines in JS do the same thing.
+</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var a = new Array();
+var b = [];
+</com:TTextHighlighter>
+<p>
+ As I'm sure you already know, you can access individual items in an array
+ by using the square brackets:
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var a = ['first', 'second', 'third'];
+var v1 = a[0];
+var v2 = a[1];
+var v3 = a[2];
+</com:TTextHighlighter>
+<p>
+
+ But you are not limited to numeric indices. You can access any member of a JS
+ object by using its name, in a string. The following example creates an empty
+ object, and adds some members by name.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var obj = {}; //new, empty object
+obj['member_1'] = 'this is the member value';
+obj['flag_2'] = false;
+obj['some_function'] = function(){ /* do something */};
+</com:TTextHighlighter>
+<p>
+ The above code has identical effect as the following:
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var obj =
+{
+ member_1:'this is the member value',
+ flag_2: false,
+ some_function: function(){ /* do something */}
+};
+</com:TTextHighlighter>
+
+<p>
+ In many ways, the idea of objects and associative arrays (hashes) in JS are not
+ distiguishable. The following two lines do the same thing too.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+obj.some_function();
+obj['some_function']();
+</com:TTextHighlighter>
+
+
+<h2 id="6506">Enough about objects, may I have a class now?</h2>
+<p>
+
+ The great power of object oriented programming languages derive from the use
+ of classes. I don't think I would have guessed how classes are defined in JS
+ using only my previous experience with other languages. Judge for yourself.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+//defining a new class called Pet
+var Pet = function(petName, age)
+{
+ this.name = petName;
+ this.age = age;
+};
+
+//let's create an object of the Pet class
+var famousDog = new Pet('Santa\'s Little Helper', 15);
+alert('This pet is called ' + famousDog.name);
+</com:TTextHighlighter>
+<p>
+ Let's see how we add a method to our <tt>Pet</tt> class. We will be using the
+ <tt>prototype</tt> property that all classes have. The <tt>prototype</tt>
+ property is an object that contains all the members that any object of the class will have.
+ Even the default JS classes, like <tt>String</tt>, <tt>Number</tt>,
+ and <tt>Date</tt> have a <tt>prototype</tt> object that we
+ can add methods and properties to and make any object of that class automatically gain this new member.
+</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+Pet.prototype.communicate = function()
+{
+ alert('I do not know what I should say, but my name is ' + this.name);
+};
+</com:TTextHighlighter>
+<p>
+ That's when a library like <a href="http://www.sergiopereira.com/articles/prototype.js.html">prototype.js</a> comes in
+ handy. If we are using prototype.js, we can make our code look cleaner (at least in my opinion.)
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var Pet = Class.create();
+Pet.prototype =
+{
+ //our 'constructor'
+ initialize: function(petName, age)
+ {
+ this.name = petName;
+ this.age = age;
+ },
+
+ communicate: function()
+ {
+ alert('I do not know what I should say, but my name is ' + this.name);
+ }
+};
+</com:TTextHighlighter>
+
+<h2 id="6507">Functions as arguments, an interesting pattern</h2>
+<p>
+ If you have never worked with languages that support closures
+ you may find the following idiom too funky.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var myArray = ['first', 'second', 'third'];
+myArray.each( function(item, index)
+{
+ alert('The item in the position #' + index + ' is:' + item);
+});
+</com:TTextHighlighter>
+<p>
+
+ Whoa! Let's explain what is going on here before you decide I've gone too
+ far and navigate to a better article than this one.
+</p>
+<p>
+ First of all, in the above example we are using the prototype.js library, which
+ adds the each function to the Array class. The each function accepts one
+ argument that is a function object. This function, in turn, will be called once
+ for each item in the array, passing two arguments when called, the item and the index
+ for the current item. Let's call this function our iterator function.
+ We could have also written the code like this.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+function myIterator(item, index)
+{
+ alert('The item in the position #' + index + ' is:' + item);
+}
+
+var myArray = ['first', 'second', 'third'];
+myArray.each( myIterator );
+</com:TTextHighlighter>
+<p>
+ But then we would not be doing like all the cool kids in school, right?
+ More seriously, though, this last format is simpler to understand but causes
+ us to jump around in the code looking for the myIterator function. It's nice
+ to have the logic of the iterator function right there in the same place
+ it's called. Also, in this case, we will not need the iterator function anywhere
+ else in our code, so we can transform it into an anonymous function without penalty.
+</p>
+
+<h2 id="6508">This is <tt>this</tt> but sometimes <tt>this</tt> is also that</h2>
+<p>
+
+ One of the most common troubles we have with JS when we start writing our code
+ it the use of the <tt>this</tt> keyword. It could be a real
+ tripwire.
+</p>
+<p>
+ As we mentioned before, a function is also an object in JS, and sometimes we
+ do not notice that we are passing a function around.
+</p>
+<p>
+ Take this code snippet as an example.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+function buttonClicked()
+{
+ alert('button ' + this.id + ' was clicked');
+}
+
+var myButton = document.getElementById('someButtonID');
+var myButton2 = document.getElementById('someOtherButtonID');
+myButton.onclick = buttonClicked;
+myButton2.onclick = buttonClicked;
+</com:TTextHighlighter>
+<p>
+ Because the buttonClicked function is defined outside any object we may tend to
+ think the <tt>this</tt> keyword will contain a reference to
+ the <tt>window</tt> or <tt>document</tt>
+ object (assuming this code is in the middle of an HTML page viewed in a browser.)
+</p>
+
+<p>
+ But when we run this code we see that it works as intended and displays the <tt>id</tt> of
+ the clicked button. What happened here is that we made the onclick method of each button contain the
+ <tt>buttonClicked</tt> object reference, replacing whatever was there before. Now
+ whenever the button is clicked, the browser will execute something similar to the following line.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+myButton.onclick();
+</com:TTextHighlighter>
+<p>
+
+ That isn't so confusing afterall, is it? But see what happens you start having other
+ objects to deal with and you want to act on these object upon events like the button's click.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var myHelper =
+{
+ formFields: [ ],
+ emptyAllFields: function()
+ {
+ for(i=0; i < this.formFields.length; i++)
+ {
+ var elementID = this.formFields[i];
+ var field = document.getElementById(elementID);
+ field.value = '';
+ }
+ }
+};
+
+//tell which form fields we want to work with
+myHelper.formFields.push('txtName');
+myHelper.formFields.push('txtEmail');
+myHelper.formFields.push('txtAddress');
+
+//clearing the text boxes:
+myHelper.emptyAllFields();
+
+var clearButton = document.getElementById('btnClear');
+clearButton.onclick = myHelper.emptyAllFields;
+</com:TTextHighlighter>
+<p>
+ So you think, nice, now I can click the Clear button on my page and those three text boxes
+ will be emptied. Then you try clicking the button only to get a runtime error. The error
+ will be related to (guess what?) the <tt>this</tt> keyword.
+ The problem is that <tt>this.formFields</tt> is not defined if
+ <tt>this</tt> containz a referece to the button, which is
+ precisely what's happening. One quick solution would be to rewrite our last line of code.
+</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+clearButton.onclick = function()
+{
+ myHelper.emptyAllFields();
+};
+</com:TTextHighlighter>
+<p>
+ That way we create a brand new function that calls our helper method within the helper object's context.
+</p>
+</com:TContent>
\ No newline at end of file diff --git a/demos/quickstart/protected/pages/Advanced/Scripts1.page b/demos/quickstart/protected/pages/Advanced/Scripts1.page new file mode 100644 index 00000000..f11a2f9d --- /dev/null +++ b/demos/quickstart/protected/pages/Advanced/Scripts1.page @@ -0,0 +1,561 @@ +<com:TContent ID="body" >
+
+<h1 id="6601">Developer Notes for prototype.js</h1>
+This guide is based on the <a href="http://www.sergiopereira.com/articles/prototype.js.html">
+Developer Notes for prototype.js</a> by Sergio Pereira.
+
+<h2 id="6603">What is that?</h2>
+<p>
+In case you haven't already used it, <a href="http://prototype.conio.net">prototype.js</a> is a
+ JavaScript library written by <a href="http://www.conio.net">Sam Stephenson</a>.
+ This amazingly well thought and well written piece of <b>standards-compliant</b> code takes a lot of
+ the burden associated with creating rich, highly interactive web pages that characterize the Web 2.0 off your back.
+</p>
+
+<p>
+ If you tried to use this library recently, you probably noticed that documentation is not one
+ of its strongest points. As many other developers before me, I got my head around prototype.js by
+ reading the source code and experimenting with it. I thought it would be nice to take notes while
+ I learned and share with everybody else.
+</p>
+<p>
+ As you read the examples and the reference, developers familiar with the Ruby
+ programming language will notice an intentional similarity between Ruby's
+ built-in classes and many of the extensions implemented by this library.
+</p>
+
+
+<h2 id="6604">Using the <tt>$()</tt> function</h2>
+<p>
+ The <tt>$()</tt> function is a handy shortcut to the all-too-frequent <tt>document.getElementById()</tt> function
+ of the DOM. Like the DOM function, this one returns the element that has the id passed as an argument.
+</p>
+
+<p>
+ Unlike the DOM function, though, this one goes further. You can pass more than one id and
+ <tt>$()</tt> will return an <tt>Array</tt> object with
+ all the requested elements. The example below should illustrate this.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+<com:TClientScript UsingClientScripts="prado" />
+<div id="myDiv">
+ <p>This is a paragraph</p>
+</div>
+
+<div id="myOtherDiv">
+ <p>This is another paragraph</p>
+</div>
+
+<input type="button" value=Test1 onclick="test1();" />
+<input type="button" value=Test2 onclick="test2();" />
+
+<script type="text/javascript">
+/*<![CDATA[*/
+function test1()
+{
+ var d = $('myDiv');
+ alert(d.innerHTML);
+}
+
+function test2()
+{
+ var divs = $('myDiv','myOtherDiv');
+ for(i=0; i<divs.length; i++)
+ {
+ alert(divs[i].innerHTML);
+ }
+}
+/*]]>*/
+</script>
+</com:TTextHighlighter>
+<p>
+ Another nice thing about this function is that you can pass either the <tt>id</tt> string or the element object itself,
+ which makes this function very useful when creating other functions that can also take either form of argument.
+</p>
+
+<h2 id="6605">Using the <tt>$F()</tt> function</h2>
+
+<p>
+ The <tt>$F()</tt> function is a another welcome shortcut. It returns the value of any field input control,
+ like text boxes or drop-down lists. The function can take as argument either the element <tt>id</tt> or the element object itself.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+<input type="text" id="userName" value="Joe Doe" />
+<input type="button" value=Test3 onclick="test3();" />
+
+<script type="text/javascript">
+/*<![CDATA[*/
+function test3()
+{
+ alert($F('userName'));
+}
+/*]]>*/
+</script>
+</com:TTextHighlighter>
+
+<h2 id="6606">Using the <tt>$A()</tt> function</h2>
+
+<p>
+ The <tt>$A()</tt> function converts the single argument it receives
+ into an <tt>Array</tt> object.
+</p>
+<p>
+ This function, combined with the extensions for the Array class,
+ makes it easier to convert or copy any enumerable list into an
+ <tt>Array</tt> object. One suggested use is to convert DOM
+ <tt>NodeLists</tt> into regular arrays, which can be traversed
+ more efficiently. See example below.
+</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+<select id="lstEmployees" size="10" >
+ <option value="5">Buchanan, Steven</option>
+ <option value="8">Callahan, Laura</option>
+ <option value="1">Davolio, Nancy</option>
+</select>
+
+<input type="button" value="Show the options" onclick="showOptions();" />
+
+<script type="text/javascript">
+/*<![CDATA[*/
+function showOptions()
+{
+ var someNodeList = $('lstEmployees').options;
+ var nodes = $A(someNodeList);
+
+ nodes.each(function(node)
+ {
+ alert(node.nodeName + ': ' + node.innerHTML);
+ });
+}
+/*]]>*/
+</script>
+</com:TTextHighlighter>
+
+<h2 id="6607">Using the <tt>$H()</tt> function</h2>
+<p>
+ The <tt>$H()</tt> function converts
+ objects into enumerable Hash objects that
+ resemble associative arrays.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+function testHash()
+{
+ //let's create the object
+ var a =
+ {
+ first: 10,
+ second: 20,
+ third: 30
+ };
+
+ //now transform it into a hash
+ var h = $H(a);
+ alert(h.toQueryString());
+
+ //displays: first=10&second=20&third=30
+}
+</com:TTextHighlighter>
+
+<h2 id="6608">Enumerating... Wow! Damn! Wahoo!</h2>
+<p>
+ We are all familar with for loops. You know, create yourself an array, populate it with
+ elements of the same kind, create a loop control structure (for, foreach, while, repeat, etc,)
+ access each element sequentially, by its numeric index, and do something with the element.
+</p>
+<p>
+ When you come to think about it, almost every time you have an array in your code it
+ means that you'll be using that array in a loop sooner or later. Wouldn't it be nice
+ if the array objects had more functionality to deal with these iterations? Yes, it would,
+ and many programming languages provide such functionality in their arrays or equivalent
+ structures (like collections and lists.)
+</p>
+
+<p>
+ Well, it turns out that prototype.js gives us the Enumerable
+ object, which implements a plethora of tricks for us to use when dealing with iterable data.
+ The prototype.js library goes one step further and extends the
+ <tt>Array</tt> class with all the methods of <tt>Enumerable</tt>.
+</p>
+
+<a name="Loops"></a>
+<h3 id="6617">Loops and iterator</h3>
+<p>
+ In standard javascript, if you wanted to sequentially display the elements of an array,
+ you could very well write something like this.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+<script type="text/javascript">
+/*<![CDATA[*/
+function showList()
+{
+ var simpsons = ['Homer', 'Marge', 'Lisa', 'Bart', 'Meg'];
+ for(i=0; i < simpsons.length; i++)
+ {
+ alert(simpsons[i]);
+ }
+}
+/*]]>*/
+</script>
+
+<input type="button" value="Show List" onclick="showList();" />
+</com:TTextHighlighter>
+<p>
+ With our new best friend, prototype.js, we can rewrite this loop like this.
+</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+function showList()
+{
+ var simpsons = ['Homer', 'Marge', 'Lisa', 'Bart', 'Meg'];
+ simpsons.each( function(familyMember)
+ {
+ alert(familyMember);
+ });
+}
+</com:TTextHighlighter>
+<p>
+ You are probably thinking "big freaking deal...just a weird syntax for the same old thing."
+ Well, in the above example, yes, there's nothing too earth shattering going on. Afterall,
+ there's not much to be changed in such a drop-dead-simple example. But
+ keep reading, nonetheless.
+</p>
+<p>
+ Before we move on. Do you see this function that is being passed as an argument
+ to the <tt>each</tt> method? Let's start referring to it as an
+ <b>iterator</b> function.
+</p>
+
+<h3 id="6618">Your arrays on steroids</h3>
+
+<p>
+ Like we mentioned above, it's very common for all the elements in your array to be of
+ the same kind, with the same properties and methods. Let's see how we can take advantage
+ of iterator functions with our new souped-up arrays.
+</p>
+<p>
+ Finding an element according to a criteria.
+<p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+<script type="text/javascript">
+/*<![CDATA[*/
+function findEmployeeById(emp_id)
+{
+ var listBox = $('lstEmployees')
+ var options = $A(listBox.options);
+ var opt = options.find( function(employee)
+ {
+ return (employee.value == emp_id);
+ });
+
+ alert(opt.innerHTML); //displays the employee name
+}
+/*]]>*/
+</script>
+
+<select id="lstEmployees" size="10" >
+ <option value="5">Buchanan, Steven</option>
+ <option value="8">Callahan, Laura</option>
+ <option value="1">Davolio, Nancy</option>
+</select>
+
+<input type="button" value="Find Laura" onclick="findEmployeeById(8);" />
+</com:TTextHighlighter>
+
+<p>
+ Now let's kick it up another notch. See how we can filter out
+ items in arrays, then retrieve just a desired member from each
+ element.
+<p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+<script type="text/javascript">
+/*<![CDATA[*/
+function showLocalLinks(paragraph)
+{
+ paragraph = $(paragraph);
+ var links = $A(paragraph.getElementsByTagName('a'));
+
+ //find links that do not start with 'http'
+ var localLinks = links.findAll( function(link)
+ {
+ var start = link.href.substring(0,4);
+ return start !='http';
+ });
+
+ //now the link texts
+ var texts = localLinks.pluck('innerHTML');
+
+ //get them in a single string
+ var result = texts.inspect();
+ alert(result);
+}
+/*]]>*/
+</script>
+
+<p id="someText">
+ This <a href="http://othersite.com/page.html">text</a> has
+ a <a href="#localAnchor">lot</a> of
+ <a href="#otherAnchor">links</a>. Some are
+ <a href="http://wherever.com/page.html">external</a>
+ and some are <a href="#someAnchor">local</a>
+</p>
+<input type=button value="Find Local Links"
+ onclick="showLocalLinks('someText')" />
+</com:TTextHighlighter>
+<p>
+ It takes just a little bit of practice to get completely addicted to this syntax.
+ Next we will go through the available functions with the following example.
+</p>
+<h1 id="6602">Enumerable Functions</h1>
+The sample data for the following examples.
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var Fixtures =
+{
+ Products:
+ [
+ {name: 'Basecamp', company: '37signals', type: 'Project Management'},
+ {name: 'Shopify', company: 'JadedPixel', type: 'E-Commerce'},
+ {name: 'Mint', company: 'Shaun Inman',type: 'Statistics'}
+ ],
+
+ Artist:
+ [
+ 'As I Lay Dying',
+ '36 Crazyfist',
+ 'Shadows Fall',
+ 'Trivium',
+ 'In Flames'
+ ],
+
+ Numbers: [0, 1, 4, 5, 98, 32, 12, 9]
+};
+
+var F = Fixtures;
+</com:TTextHighlighter>
+
+<h2 id="6609"><tt>Enumerable.each</tt> function</h2>
+<p>I used to find myself writing a lot of for loops. Although,
+Prototype doesn’t by any means eliminate the need to do for loops,
+it does give you access to what I consider to be a cleaner, easier to read method in each.
+<com:TTextHighlighter Language="javascript" CssClass="source">
+for(var i = 0; i < F.Numbers.length; i++)
+{
+ Logger.info(F.Numbers[i]);
+}
+</com:TTextHighlighter>
+<p>
+The <tt>each</tt> function allows us to iterate over these objects Ruby style.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+F.Numbers.each(function(num)
+{
+ Logger.info(num);
+});
+
+//Output
+0
+1
+4
+5
+98
+32
+12
+9
+</com:TTextHighlighter>
+
+<p>The <tt>each</tt> function takes one argument, an <b>iterator</b> function.
+This iterator is invoked once for every item in the array, and that item
+along with the optional index is passed to the iterator. So if
+we also needed the index we could do something like the code below.
+</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+F.Numbers.each(function(num, index)
+{
+ Logger.info(index + ": " + num);
+});
+
+//Output
+0: 0
+1: 1
+2: 4
+3: 5
+4: 98
+5: 32
+6: 12
+7: 9
+</com:TTextHighlighter>
+
+<h2 id="6610">Hash key/value pairs</h2>
+<p>Hashes can be created by wrapping an Object (associative array) in
+<tt>$H()</tt> and can have their key/value pairs exposed.</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+$H(F.Products[0]).each(function(product)
+{
+ Logger.info(product.key + ": " + product.value);
+});
+
+//Outputs
+name: Basecamp
+company: 37signals
+type: Project Management
+</com:TTextHighlighter>
+<p>
+We can also directly access the keys and values of a Hash without iterating over it.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+$H(F.Products[1]).keys();
+//Outputs name,company,type
+
+$H(F.Products[1]).values();
+//Outputs Shopify,JadedPixel,E-Commerce
+</com:TTextHighlighter>
+
+<h2 id="6611"><tt>Enumerable.collect</tt> function</h2>
+
+<p>The <tt>collect</tt> function allows you to iterate over an <tt>Array</tt> and return the
+results as a new array. Each item returned as a result of the iteration will be
+pushed onto the end of the new array.</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var companies = F.Products.collect(function(product)
+{
+ return product.company;
+});
+
+Logger.info(companies.join(', '));
+
+// Outputs
+// 37signals, JadedPixel, Shaun Inman
+</com:TTextHighlighter>
+
+<p>You can even join on the end of the block.</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+return F.Products.collect(function(product)
+{
+ return product.company;
+}).join(', ');
+</com:TTextHighlighter>
+
+<h2 id="6612"><tt>Enumerable.include</tt> function</h2>
+
+<p>The <tt>include</tt> function allows you to check if a value is included in an array
+and returns true or false depending on if a match was made. Assuming I put
+up a form asking the user to name some artist in my iTunes playlist,
+we could do something like the code below. Prime candidate for some conditional madness.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+return F.Artists.include('Britney Spears'); // returns false
+</com:TTextHighlighter>
+
+<h2 id="6613"><tt>Enumerable.inject</tt> function</h2>
+
+<p>The <tt>inject</tt> function is good for getting a collective sum from an array of
+values. For instance, to add up all the numbers.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var score = F.Numbers.inject(0, function(sum, value)
+{
+ return sum + value;
+});
+
+Logger.info(score);
+//Output 161
+</com:TTextHighlighter>
+
+<p>The first argument to <tt>inject</tt> is just an initial value that
+would be added to the sum, so if we added 1 instead of 0, the output would be 162.</p>
+
+<h2 id="6614"><tt>Enumerable.findAll</tt> function</h2>
+<p>
+When given an Array, the <tt>findAll</tt> function will return an array of
+items for which the iterator evaluated to true. Basically, it allows you to
+build a new array of values based on some search criteria.
+If we wanted to find all products whose type was “E-Commerce”
+we could do something like the code below.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var ecom = F.Products.findAll(function(product)
+{
+ return product.type == 'E-Commerce';
+});
+
+Logger.info(ecom[0].company + " produces " + ecom[0].name);
+
+//Outputs
+JadedPixel produces Shopify
+</com:TTextHighlighter>
+
+<p>Note that even if only one match is made, just as in this case,
+the result is still returned as an array. In that case,
+<tt>ecom.company</tt> would return <tt>undefined</tt>.</p>
+
+<h2 id="6615"><tt>Enumerable.detect</tt> function</h2>
+<p>Unlike the <tt>findAll</tt> function, the <tt>detect</tt> function will only
+return the first item for which the expression inside
+the iterator is true. So, if we wanted to find the first number that
+was greater than 5 we’d do something like the code below.
+</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+var low = F.Numbers.detect(function(num)
+{
+ return num > 5
+});
+
+Logger.info(low);
+//Outputs 98
+</com:TTextHighlighter>
+
+<p>Even though, there are other numbers above 5 in our array, detect
+only gives us the first match back.</p>
+
+<h2 id="6616"><tt>Enumerable.invoke</tt> function</h2>
+
+<p>The <tt>invoke</tt> function allows us to pass a method as a string and
+have that method invoked. For instance, if we wanted to sort
+our array of artists we’d do something like this:</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+[F.Artists].invoke('sort')
+//Outputs 36 Crazyfist,As I Lay Dying,In Flames,Shadows Fall,Trivium
+</com:TTextHighlighter>
+
+<p>Why not just use <tt>F.Artists.sort</tt>? Well, for the example above
+we could do just that, but here is where <tt>invoke</tt> shines.</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+[F.Artists, F.Letters].invoke('sort');
+//Outputs 36 Crazyfist,As I Lay Dying,In Flames,...
+</com:TTextHighlighter>
+<p>So we invoked sort for each sub-array. Note that the code below will not work.</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+F.Artists.invoke('sort');
+</com:TTextHighlighter>
+
+<p>The reason this will not work is because it is taking each item
+in that array and trying to apply sort to it, thus if we wrote it outright,
+it would look something like this:</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+"36 Crazy Fists".sort();
+</com:TTextHighlighter>
+<p>We could however do something like this:</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+F.Artists.invoke('toLowerCase');
+//Outputs 36 crazyfist,as i lay dying,in flames,shadows ...
+</com:TTextHighlighter>
+
+<p>
+Now, what about passing arguments to the <tt>invoke</tt> function?
+The first argument passed to <tt>invoke</tt> is the method to be invoked,
+and any other arguments beyond that will be passed as arguments to the invoked method.</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+F.Artists.invoke('concat', " is awesome ")
+//Outputs
+36 Crazyfist is awesome ,As I Lay Dying is awesome ,...
+</com:TTextHighlighter>
+
+</com:TContent>
\ No newline at end of file diff --git a/demos/quickstart/protected/pages/Advanced/Scripts2.page b/demos/quickstart/protected/pages/Advanced/Scripts2.page new file mode 100644 index 00000000..6ee6a5d8 --- /dev/null +++ b/demos/quickstart/protected/pages/Advanced/Scripts2.page @@ -0,0 +1,253 @@ +<com:TContent ID="body" >
+<h1 id="6701">DOM Events and Javascript</h1>
+
+<h2 id="6702">Basic event handling</h2>
+
+<p>The syntax for working with events looks like the code below.</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+Event.observe(element, name, observer, [useCapture]);
+</com:TTextHighlighter>
+
+<p>Assuming for a moment that we want to observe when a link was clicked,
+we could do the following:</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+// <a id="clicker" href="http://foo.com">Click me</a>
+Event.observe('clicker', 'click', function(event)
+{
+ alert('clicked!');
+});
+</com:TTextHighlighter>
+
+<p>If we wanted to get the element that fired the event, we'd do this:</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+Event.observe('clicker', 'click', function(event)
+{
+ alert(Event.element(event));
+});
+</com:TTextHighlighter>
+
+<h2 id="6703">Observing keystrokes</h2>
+
+<p>If we wanted to observe keystrokes for the entire document, we could do the following:</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+Event.observe(document, 'keypress', function(event)
+{
+ if(Event.keyCode(event) == Event.KEY_TAB)
+ alert('Tab Pressed');
+});
+</com:TTextHighlighter>
+
+<p>And lets say we wanted to keep track of what has been typed :</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+Event.observe('search', 'keypress', function(event)
+{
+ Element.update('search-results', $F(Event.element(event)));
+});
+</com:TTextHighlighter>
+
+<p>Prototype defines properties inside the event object for some
+of the more common keys, so feel free to dig around in Prototype to
+see which ones those are.</p>
+
+<p>A final note on keypress events; If you'd like to detect a
+left click you can use <tt>Event.isLeftClick(event)</tt>.</p>
+
+<h2 id="6704">Getting the coordinates of the mouse pointer</h2>
+
+<p>Drag and drop, dynamic element resizing, games, and
+much more all require the ability to track the X and Y location of
+the mouse. Prototype makes this fairly simple. The code below tracks
+the X and Y position of the mouse and spits out those values into
+an input box named mouse.</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+Event.observe(document, 'mousemove', function(event)
+{
+ $('mouse').value = "X: " + Event.pointerX(event) +
+ "px Y: " + Event.pointerY(event) + "px";
+});
+</com:TTextHighlighter>
+
+<p>If we wanted to observe the mouse location when it was
+hovering over a certain element, we'd just change the document argument to
+the id or element that was relevant.</p>
+
+<h2 id="6705">Stopping Propagation</h2>
+
+<p><tt>Event.stop(event)</tt> will stop the propagation of an event .</p>
+
+<h2 id="6706">Events, Binding, and Objects</h2>
+
+<p>Everything has been fairly straight forward so far, but things
+start getting a little tricker when you need to work with events in
+and object-oriented environment. You have to deal with binding and funky
+looking syntax that might take a moment to get your head around.</p>
+
+<p>Lets look at some code so you can get a better understanding of what I'm talking about.</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+EventDispenser = Class.create();
+EventDispenser.prototype =
+{
+ initialize: function(list)
+ {
+ this.list = list;
+
+ // Observe clicks on our list items
+ $$(this.list + " li").each(function(item)
+ {
+ Event.observe(item, 'click', this.showTagName.bindEvent(this));
+ }.bind(this));
+
+ // Observe when a key on the keyboard is pressed.
+ // In the observer, we check for
+ // the tab key and alert a message if it is pressed.
+ Event.observe(document, 'keypress', this.onKeyPress.bindEvent(this));
+
+ // Observe our fake live search box. When a user types
+ // something into the box, the observer will take that
+ // value(-1) and update our search-results div with it.
+ Event.observe('search', 'keypress', this.onSearch.bindEvent(this));
+
+ Event.observe(document, 'mousemove', this.onMouseMove.bindEvent(this));
+ },
+
+ // Arbitrary functions to respond to events
+ showTagName: function(event)
+ {
+ alert(Event.element(event).tagName);
+ },
+
+ onKeyPress: function(event)
+ {
+ var code = event.keyCode;
+ if(code == Event.KEY_TAB)
+ alert('Tab key was pressed');
+ },
+
+ onSearch: function(event)
+ {
+ Element.update('search-results', $F(Event.element(event)));
+ },
+
+ onMouseMove: function(event)
+ {
+ $('mouse').value = "X: " + Event.pointerX(event) +
+ "px Y: " + Event.pointerY(event) + "px";
+ }
+}
+</com:TTextHighlighter>
+<p>Whoa! What's going on here? Well, we've defined our a
+custom class <tt>EventDispenser</tt>. We're going to be using this class
+to setup events for our document. Most of this code is a
+rewrite of the code we looked at earlier except this time, we
+are working from inside an object.</p>
+
+<p>Looking at the <tt>initialize</tt> method, we can really see how
+things are different now. Take a look at the code below:</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+// Observe clicks on our list items
+$$(this.list + " li").each(function(item)
+{
+ Event.observe(item, 'click', this.showTagName.bindEvent(this));
+}.bind(this));
+</com:TTextHighlighter>
+
+<p>We've got iterators, binding and all sorts of stuff going on.
+Lets break down what this chunk of code is doing.</p>
+
+<p>First we are hunting for a collection of elements based on
+it's Css selector. This uses the Prototype selector function <tt>$$()</tt>.
+After we've found the list items we are dealing with we send
+those into an each iteration where we will add our observers.</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+Event.observe(item, 'click', this.showTagName.bindEvent(this));
+</com:TTextHighlighter>
+
+<p>Now looking at the code above, you'll notice the <tt>bindEvent</tt> function.
+This takes the method before it <tt>showTagName</tt> and treats it as the
+method that will be triggered when, in this case,
+someone clicks one of our list items.</p>
+
+<p>You'll also notice we pass this as an argument to the <tt>bindEvent</tt> function.
+This simply allows us to reference the object in context <tt>EventDispenser</tt>
+inside our function <tt>showTagName(event)</tt>. If the <tt>showTagName</tt> function
+requires additional parameters, you can attach them to the later parameters of <tt>bindEvent</tt>. For example</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+this.showTagName.bindEvent(this, param1, param2);
+
+//where the showTagName function is defined as
+showTime : function (event, param1, param2) { ... }
+</com:TTextHighlighter>
+
+<p>Moving on, you'll see <tt>bind(this)</tt> attached to our iterator function.
+This really has nothing to do with events, it is only here to allow me to
+use <tt>this</tt> inside the iterator. If we didn't use <tt>bind(this)</tt>, I couldn't
+reference the method <tt>showTagName</tt> inside the iterator.</p>
+
+<p>Ok, so we'll move on to looking at our methods that actually get
+called when an event occurs. Since we've been dealing with <tt>showTagName</tt>, lets look at it.</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+showTagName: function(event)
+{
+ alert(Event.element(event).tagName);
+}
+</com:TTextHighlighter>
+
+<p>As you can see, this function accepts one argument--the event.
+In order for us to get the element which fired the event we need to
+pass that argument to <tt>Event.element</tt>. Now we can manipulate it at will.</p>
+
+<p>This covers the most confusing parts of our code. The text above is also
+relevant to the remaining parts of our code. If there is anything about
+this you don't understand, feel free to ask questions in the forum.</p>
+
+<h2 id="6707">Removing Event Listeners</h2>
+
+<p>This one threw me for a loop the first time I tried to use it.
+I tried something similar to what I did in the <tt>Event.observe</tt>
+call with the exception of using <tt>stopObserving</tt>, but nothing seemed
+to change. In other words, the code below does <b>NOT</b> work.</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+$$(this.list + " li").each(function(item)
+{
+ Event.stopObserving(item, 'click', this.showTagName);
+}.bind(this));
+</com:TTextHighlighter>
+
+<p>What's the deal here? The reason this doesn't work is because there
+is no pointer to the observer. This means that when we passed <tt>this.showTagName</tt>
+in the <tt>Event.observe</tt> method before hand, we passed it as an
+anonymous function. We can't reference an anonymous function
+because it simply doesn't have a pointer.</p>
+
+<p>So how do we get the job done? All we need to do is give the
+observing function a pointer, or the jargon free version: Set a variable
+that points to <tt>this.showTagName</tt>. Ok, lets change our code a bit.</p>
+
+<com:TTextHighlighter Language="javascript" CssClass="source">
+this.showTagObserver = this.showTagName.bindEvent(this);
+
+// Observe clicks on our list items
+$$(this.list + " li").each(function(item)
+{
+ Event.observe(item, 'click', this.showTagObserver);
+}.bind(this));
+</com:TTextHighlighter>
+
+<p>Now we can remove the event listeners from our list like this:</p>
+<com:TTextHighlighter Language="javascript" CssClass="source">
+$$(this.list + " li").each(function(item)
+{
+ Event.stopObserving(item, 'click', this.showTagObserver);
+}.bind(this));
+</com:TTextHighlighter>
+
+</com:TContent>
\ No newline at end of file diff --git a/demos/quickstart/protected/pages/Advanced/Scripts3.page b/demos/quickstart/protected/pages/Advanced/Scripts3.page new file mode 100644 index 00000000..9883f43e --- /dev/null +++ b/demos/quickstart/protected/pages/Advanced/Scripts3.page @@ -0,0 +1,32 @@ +<com:TContent ID="body" >
+<h1 id="6801">Javascript in Prado, Questions and Answers</h1>
+<h2 id="6802">How do I include the predefined javascript libraries?</h2>
+<ul><li>Adding libraries in the template
+<com:TTextHighlighter Language="prado" CssClass="source">
+<com:TClientScript UsingPradoScripts="effects" />
+</com:TTextHighlighter>
+ </li>
+ <li>Adding libraries in PHP code
+ <com:TTextHighlighter Language="php" CssClass="source">
+$this->getPage()->getClientScript()->registerPradoScript("effects");
+ </com:TTextHighlighter>
+ </li>
+</ul>
+The available packaged libraries included in Prado are
+<ul>
+ <li><tt>prado</tt> : basic prado javascript framework based on Prototype</li>
+ <li><tt>effects</tt> : visual effects from script.aculo.us</li>
+ <li><tt>ajax</tt> : ajax and callback related based on Prototype</li>
+ <li><tt>validator</tt> : validation</li>
+ <li><tt>logger</tt> : javascript logger and object browser</li>
+ <li><tt>datepicker</tt> : datepicker</li>
+ <li><tt>rico</tt> : Rico library</li>
+ <li><tt>colorpicker</tt> : colorpicker</li>
+</ul>
+
+<p>The dependencies for each library are automatically resolved. Components
+that require a particular library will also automatically load the necessary libraries.
+For example, if you add a TDatePicker component on the page, the <tt>datapicker</tt>
+and its dependencies will be automatically included on the page.</p>
+
+</com:TContent>
\ No newline at end of file diff --git a/demos/quickstart/protected/pages/Advanced/Security.page b/demos/quickstart/protected/pages/Advanced/Security.page index b6de7251..9be7946a 100644 --- a/demos/quickstart/protected/pages/Advanced/Security.page +++ b/demos/quickstart/protected/pages/Advanced/Security.page @@ -1,8 +1,8 @@ <com:TContent ID="body" >
-<h1>Security</h1>
+<h1 id="5601">Security</h1>
-<h2>Viewstate Protection</h2>
+<h2 id="5602">Viewstate Protection</h2>
<p>
Viewstate lies at the heart of PRADO. Viewstate represents data that can be used to restore pages to the state that is last seen by end users before making the current request. By default, PRADO uses hidden fields to store viewstate information.
</p>
@@ -26,7 +26,7 @@ HMAC check requires a private key that should be secret to end users. Developers HMAC check does not prevent end users from reading the viewstate content. An added security measure is to encrypt the viewstate information so that end users cannot decipher it. To enable viewstate encryption, set the <tt>EnableStateEncryption</tt> of pages to true. This can be done in <a href="?page=Configurations.PageConfig">page configurations</a> or in page code. Note, encrypting viewstate may degrade the application performance. A better strategy is to store viewstate on the server side, rather than the default hidden field.
</p>
-<h2>Cross Site Scripting Prevention</h2>
+<h2 id="5603">Cross Site Scripting Prevention</h2>
<p>
Cross site scripting (also known as XSS) occurs when a web application gathers malicious data from a user. Often attackers will inject JavaScript, VBScript, ActiveX, HTML, or Flash into a vulnerable application to fool other application users and gather data from them. For example, a poorly design forum system may display user input in forum posts without any checking. An attacker can then inject a piece of malicious JavaScript code into a post so that when other users read this post, the JavaScript runs unexpectedly on their computers.
</p>
@@ -37,7 +37,7 @@ One of the most important measures to prevent XSS attacks is to check user input PRADO incorporates the work of <a href="http://pixel-apes.com/safehtml/">SafeHTML</a> and provides developers with a useful component called <tt>TSafeHtml</tt>. By enclosing content within a <tt>TSafeHtml</tt> component tag, the enclosed content are ensured to be safe to end users. In addition, the commonly used <tt>TTextBox</tt> has a <tt>SafeText</tt> property which contains user input that are ensured to be safe if displayed directly to end users.
</p>
-<h2>Cookie Attack Prevention</h2>
+<h2 id="5604">Cookie Attack Prevention</h2>
<p>
Protecting cookies from being attacked is of extreme important, as session IDs are commonly stored in cookies. If one gets hold of a session ID, he essentially owns all relevant session information.
</p>
diff --git a/demos/quickstart/protected/pages/Advanced/State.page b/demos/quickstart/protected/pages/Advanced/State.page index 8d69d6a4..051090e9 100644 --- a/demos/quickstart/protected/pages/Advanced/State.page +++ b/demos/quickstart/protected/pages/Advanced/State.page @@ -1,11 +1,11 @@ <com:TContent ID="body" >
-<h1>Persistent State</h1>
+<h1 id="6001">Persistent State</h1>
<p>
Web applications often need to remember what an end user has done in previous page requests so that the new page request can be served accordingly. State persistence is to address this problem. Traditionally, if a page needs to keep track of user interactions, it will resort to session, cookie, or hidden fields. PRADO provides a new line of state persistence schemes, including view state, control state, and application state.
</p>
-<h2>View State</h2>
+<h2 id="6002">View State</h2>
<p>
View state lies at the heart of PRADO. With view state, Web pages become stateful and are capable of restoring pages to the state that end users interacted with before the current page request. Web programming thus resembles to Windows GUI programming, and developers can think continuously without worrying about the roundtrips between end users and the Web server. For example, with view state, a textbox control is able to detect if the user input changes the content in the textbox.
</p>
@@ -22,7 +22,7 @@ where <tt>$this</tt> refers to the control object, <tt>Caption</tt> is a unique $caption = $this->getViewState('Caption');
</com:TTextHighlighter>
-<h2>Control State</h2>
+<h2 id="6003">Control State</h2>
<p>
Control state is like view state in every aspect except that control state cannot be disabled. Control state is intended to be used for storing crucial state information without which a page or control may not work properly.
</p>
@@ -34,7 +34,7 @@ $this->setControlState('Caption',$caption); $caption = $this->getControlState('Caption');
</com:TTextHighlighter>
-<h2>Application State</h2>
+<h2 id="6004">Application State</h2>
<p>
Application state refers to data that is persistent across user sessions and page requests. A typical example of application state is the user visit counter. The counter value is persistent even if the current user session terminates. Note, view state and control state are lost if the user requests for a different page, while session state is lost if the user session terminates.
</p>
@@ -46,7 +46,7 @@ $application->setGlobalState('Caption',$caption); $caption = $application->getGlobalState('Caption');
</com:TTextHighlighter>
-<h2>Session State</h2>
+<h2 id="6005">Session State</h2>
<p>
PRADO encapsulates the traditional session management in <tt>THttpSession</tt> module. The module can be accessed from within any component by using <tt>$this->Session</tt>, where <tt>$this</tt> refers to the component object.
</p>
diff --git a/demos/quickstart/protected/pages/Advanced/Themes.page b/demos/quickstart/protected/pages/Advanced/Themes.page index ba5585e7..ef593c65 100644 --- a/demos/quickstart/protected/pages/Advanced/Themes.page +++ b/demos/quickstart/protected/pages/Advanced/Themes.page @@ -1,18 +1,18 @@ <com:TContent ID="body" >
-<h1>Themes and Skins</h1>
+<h1 id="5901">Themes and Skins</h1>
-<h2>Introduction</h2>
+<h2 id="5902">Introduction</h2>
<p>
Themes in Prado provide a way for developers to provide a consistent look-and-feel across an entire web application. A theme contains a list of initial values for properties of various control types. When applying a theme to a page, all controls on that page will receive the corresponding initial property values from the theme. This allows themes to interact with the rich property sets of the various PRADO controls, meaning that themes can be used to specify a large range of presentational properties that other theming methods (e.g. CSS) cannot. For example, themes could be used to specify the default page size of all data grids across an application by specifying a default value for the <tt>PageSize</tt> property of the <tt>TDataGrid</tt> control.
</p>
-<h2>Understanding Themes</h2>
+<h2 id="5903">Understanding Themes</h2>
<p>
A theme is a directory consists of skin files, javascript files and CSS files. Any javascript or CSS files contained in a theme will be registered with the page that the theme is applied to. A skin is a set of initial property values for a particular control type. A control type may have one or several skins, each identified by a unqiue <tt>SkinID</tt>. When applying a theme to a page, a skin is applied to a control if the control type and the <tt>SkinID</tt> value both match to those of the skin. Note, if a skin has an empty <tt>SkinID</tt> value, it will apply to all controls of the particular type whose <tt>SkinID</tt> is not set or empty. A skin file consists of one or several skins, for one or several control types. A theme is the union of skins defined in all skin files.
</p>
-<h2>Using Themes</h2>
+<h2 id="5904">Using Themes</h2>
<p>
To use a theme, you need to set the <tt>Theme</tt> property of the page with the theme name, which is the theme directory name. You may set it in either <a href="?page=Configurations.PageConfig">page configurations</a> or in the constructor or <tt>onPreInit()</tt> method of the page. You cannot set the property after <tt>onPreInit()</tt> because by that time, child controls of the page are already created (skins must be applied to controls right after they are created.)
</p>
@@ -29,7 +29,7 @@ This will apply the 'Blue' skin to the button. Note, the initial property values To use the javascript files and CSS files contained in a theme, a <tt>THead</tt> control must be placed on the page template. This is because the theme will register those files with the page and <tt>THead</tt> is the right place to load those files.
</p>
-<h2>Theme Storage</h2>
+<h2 id="5905">Theme Storage</h2>
<p>
All themes by default must be placed under the <tt>[AppEntryPath]/themes</tt> directory, where <tt>AppEntryPath</tt> refers to the directory containing the application entry script. If you want to use a different directory, configure the <tt>BasePath</tt> and <tt>BaseUrl</tt> properties of the <tt>System.Web.UI.TThemeManager</tt> module in application configuration,
</p>
@@ -44,7 +44,7 @@ All themes by default must be placed under the <tt>[AppEntryPath]/themes</tt> di </service>
</com:TTextHighlighter>
-<h2>Creating Themes</h2>
+<h2 id="5906">Creating Themes</h2>
<p>
Creating a theme involves creating the theme directory and writing skin files (and possibly javascript and CSS files). The name of skin files must be terminated with <tt>.skin</tt>. The format of skin files are the same as that of control template files. Since skin files do not define parent-child presentational relationship among controls, you cannot place a component tag within another. And any static texts between component tags are discarded. To define the aforementioned 'Blue' skin for <tt>TButton</tt>, write the following in a skin file,
</p>
|