ajax imp codes

71
Back to site Demos This site demonstrates the Ruby on Rails AJAX helpers, which use script.aculo.us effects, drag-and-drop and autocompletion. Rails Demos script.aculo.us helpers Autocompleting text fields (basic) Autocompleting text fields (customized) Shopping cart Sortable elements New AJAX features Error handling Update element helper Rails is a full-stack, open-source web framework in Ruby for writing real- world applications with joy and less code than most frameworks spend doing XML sit- ups. That quite sums it up. So, if you're still working late hours writing definitions of what's in your database because the framework you use works against and not for you -- do yourself a favour, and check out Ruby on Rails .

Upload: satyanarayana

Post on 10-Apr-2015

715 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Ajax Imp Codes

Back to site Demos

This site demonstrates the Ruby on Rails AJAX helpers, which use script.aculo.us effects, drag-and-drop and autocompletion.

Rails Demos

script.aculo.us helpers

Autocompleting text fields (basic) Autocompleting text fields (customized)

Shopping cart

Sortable elements

New AJAX features

Error handling Update element helper

Rails is a full-stack, open-source web framework in Ruby for writing real-world applications with joy and less code than most frameworks spend doing XML sit-ups. That quite sums it up. So, if you're still working late hours writing definitions of what's in your database because the framework you use works against and not for you -- do yourself a favour, and check out Ruby on Rails.

Silly easy shopping

Drag products to the cart to fill it:

Page 2: Ajax Imp Codes

Your cart:

Mug (1)

Drop items here to remove them from the cart.

View source

# view<div style="margin-bottom:20px;height:120px;"><% for product in @products %> <%= image_tag "/images/products/product#{product.id}.png", :id => "product_#{product.id}", :alt => product.title, :class => "products" %> <%= draggable_element "product_#{product.id}", :revert => true %><% end %></div>

<h2>Your cart:</h2>

<div id="cart" class="cart" style="clear:left; height:132px;margin-top:10px;"> <div id="wastebin"> Drop items here to remove them from the cart. </div> <div id="items"> <%= render :partial => "cart" %> </div> <div style="clear:both;"></div></div>

<div style="height:40px;padding-top:10px;"><p id="indicator" style="display:none;margin-top:0px;"> <%= image_tag "indicator.gif" %> Updating cart...</p></div>

<%= drop_receiving_element "cart", :update => "items", :url => { :action => "add" }, :accept => "products", :hoverclass => "cart-active",

Page 3: Ajax Imp Codes

:loading => "Element.show('indicator')", :complete => "Element.hide('indicator')" %> <%= drop_receiving_element "wastebin", :update => "items", :url => { :action => "remove" }, :accept => "cart-items", :hoverclass => "wastebin-active", :before => "Element.hide(element)", :loading => "Element.show('indicator')", :complete => "Element.hide('indicator')" %> # controllerclass ShopController < ApplicationController def index session[:cart] ||= {} @products = Product.find(:all) end def add product_id = params[:id].split("_")[1] session[:cart][product_id] = session[:cart].include?(product_id) ? session[:cart][product_id]+1 : 1 render :partial => 'cart' end def remove product_id = params[:id].split("_")[1] if session[:cart][product_id] > 1 session[:cart][product_id] = session[:cart][product_id]-1 else session[:cart].delete(product_id) end render :partial => 'cart' end end

# _cart.rhtml partial<% session[:cart].each do |product,quantity| %><div> <% quantity.times do |i| %> <%= image_tag "/images/products/product#{product}.png", :class => "cart-items", :id => "item_#{product}_#{i}", :style => "position:relative;" %> <%= draggable_element "item_#{product}_#{i}", :revert => true %> <% end %> <span class="title"> <%= Product.find(product).title + " (#{quantity})" %> </span></div>

Page 4: Ajax Imp Codes

<% end %><%= "Here's your shopping cart." if session[:cart].empty? %>

© 2005-2007 Thomas Fuchs License mir.aculo.us

Lightbox 2

How to Use

Part 1 - Setup1. Lightbox 2 uses the Prototype Framework and Scriptaculous Effects Library. You will

need to include these three Javascript files in your header (in this order). 2. <script type="text/javascript" src="js/prototype.js"></script>3. <script type="text/javascript" src="js/scriptaculous.js?

load=effects,builder"></script>4. <script type="text/javascript" src="js/lightbox.js"></script>5. Include the Lightbox CSS file (or append your active stylesheet with the Lightbox styles).

6. <link rel="stylesheet" href="css/lightbox.css" type="text/css" media="screen" />

7. Check the CSS and make sure the referenced prev.gif and next.gif files are in the right location. Also, make sure the loading.gif and close.gif files as referenced near the top of the lightbox.js file are in the right location.

Part 2 - Activate1. Add a rel="lightbox" attribute to any link tag to activate the lightbox. For example: 2. <a href="images/image-1.jpg" rel="lightbox" title="my

caption">image #1</a>

Optional: Use the title attribute if you want to show a caption.

3. If you have a set of related images that you would like to group, follow step one but additionally include a group name between square brackets in the rel attribute. For example:

4. <a href="images/image-1.jpg" rel="lightbox[roadtrip]">image #1</a>5. <a href="images/image-2.jpg" rel="lightbox[roadtrip]">image #2</a>

<a href="images/image-3.jpg" rel="lightb

How to Use

Part 1 - Setup1. Lightbox 2 uses the Prototype Framework and Scriptaculous Effects Library. You will

need to include these three Javascript files in your header (in this order). 2. <script type="text/javascript" src="js/prototype.js"></script>3. <script type="text/javascript" src="js/scriptaculous.js?

load=effects,builder"></script>

Page 5: Ajax Imp Codes

4. <script type="text/javascript" src="js/lightbox.js"></script>5. Include the Lightbox CSS file (or append your active stylesheet with the Lightbox styles).

6. <link rel="stylesheet" href="css/lightbox.css" type="text/css" media="screen" />

7. Check the CSS and make sure the referenced prev.gif and next.gif files are in the right location. Also, make sure the loading.gif and close.gif files as referenced near the top of the lightbox.js file are in the right location.

Part 2 - Activate1. Add a rel="lightbox" attribute to any link tag to activate the lightbox. For example: 2. <a href="images/image-1.jpg" rel="lightbox" title="my

caption">image #1</a>

Optional: Use the title attribute if you want to show a caption.

3. If you have a set of related images that you would like to group, follow step one but additionally include a group name between square brackets in the rel attribute. For example:

4. <a href="images/image-1.jpg" rel="lightbox[roadtrip]">image #1</a>5. <a href="images/image-2.jpg" rel="lightbox[roadtrip]">image #2</a>

<a href="images/image-3.jpg" rel="lightb

SupportIt doesn't work at all. The image opens up in a new page. What's wrong?

This is commonly caused by a conflict between scripts. Check your body tag and look for an onload attribute. Example:<body onload="MM_preloadImages(‘/images/menu_on.gif’)…;">

A quick fix to this problem is to append the initLightbox() to the onload attribute as so:<body onload="MM_preloadImages(‘/images/menu_on.gif’)…;initLightbox()">

It doesn't work if I click an image link before the page has finished loading.

The script is activated only after the page has finished loading.

The shadow overlay doesn't stretch to cover full browser window.

Remove the default margin and padding from the body tag. Add body{ margin: 0; padding: 0; } to your stylesheet.

Can I insert links in the caption?

Page 6: Ajax Imp Codes

Yes, but you need to convert quotes and greater and less than symbols into their html entity equivalents. For example:<a href="images/image-4.jpg" rel="lightbox" title="&lt;a href=&quot;link.html&quot;&gt;my link&lt;/a&gt;">Image</a>

Can I display flash, video, or other content using the script?

Sorry, photos only. For other content, google for Lightbox modifications or try an alternative script such as Cody Lindley's ThickBox.

Can the script be called from an iframe?

If you're using iframes, try the Lytebox modification which has better support.

Can I use the script in a commercial project?

Yes. It is licensed under the Creative Commons Attribution 2.5 License. A donation would be nice, hint hint.

As for proper attribution, all that is required is that you leave my name and link atop the lightbox javascript file. I do appreciate an html link, but it i

Starbox

<script type='text/javascript' src='js/prototype.js'></script><script type='text/javascript' src='js/scriptaculous.js?load=effects'></script><script type='text/javascript' src='js/starbox.js'></script>

Add starbox.css to your header.

<link rel="stylesheet" type="text/css" href="css/starbox.css" />

Upload the images to the images directory. Don't forget do modify this line in starbox.js when you put the images in a different directory.

overlayImages: '../images/starbox/',

How to use

You can turn any element into a Starbox using:

new Starbox(element, average);

Page 7: Ajax Imp Codes

More advanced Starboxes can be made using a thirth parameter with options, a few examples:

new Starbox(element, average, { stars: 10, buttons: 20, max: 10 });new Starbox(element, average, { overlay: 'big.png', ghosting: true });new Starbox(element, average, { total: 539, rated: 4.5, rerate: true });

Below are all the options you can use. Saving the rating is described in the tutorial section along with other useful examples.

new Starbox( element, // the id of your element average, // average rating to start with { buttons: 5, // amount of clickable areas className : 'default', // default class color: false, // overwrites the css style to set color on the stars duration: 0.6, // duration of revert effect, when effects are used effect: { mouseover: false, // use effects on mouseover, default false mouseout: true // use effects on mouseout, default when available } hoverColor: false, // overwrites the css hover color hoverClass: 'hover', // the css hover class color ghostColor: false, // the color of the ghost stars, if used ghosting: false, // ghosts the previous vote identity: false, // a unique value you can give each starbox indicator: false, // use an indicator, default false inverse: false, // inverse the stars, right to left locked: false, // lock the starbox to prevent voting max: 5, // the maximum rating of the starbox onRate: false, // or function(element, memo) {} // element = your starbox element // memo = { identity: identity, // rated: rated, // average: average, // max: max, // total: total // }

Page 8: Ajax Imp Codes

rated: false, // or a rating to indicate a vote has been cast ratedClass: 'rated', // class when rated rerate: false, // allow rerating overlay: 'default.png', // default star overlay image overlayImages: '../images/starbox/', // directory of images relative to the js file stars: 5, // the amount of stars total: 0 // amount of votes cast });

Styling

You can style your starboxes with CSS, in starbox.css you can find a few examples on how to do this. Note that the only thing you can not set through CSS is the overlay image.

This is one of the examples from starbox.css:

.starbox .stars { background: #cccccc; }

.starbox .rated .stars { background: #dcdcdc; }

.starbox .rated .hover .stars { background: #cccccc; }

.starbox .colorbar { background: #1e90ff; }

.starbox .hover .colorbar { background: #ffcc1c; }

.starbox .rated .colorbar { background: #64b2ff; }

.starbox .rated .hover .colorbar { background: #1e90ff; }

.starbox .ghost { background: #a1a1a1; }

.starbox .indicator { clear: both; }

TutorialsHow do I save the results to a database?

There are many ways to go about this, in a variety of languages. But since you are using Prototype, required for Starbox to work, the Ajax part of it can be used to make this task a bit easier. I will only go into the Javascript part of this since I can't cover all back-end cases. I will use Prototypes Ajax.Request to call a file that saves to the database and I will also show you how to post the rating using a regular form.

Using a Form

When you add starboxes within a form tag, all it's data will by submitted using this format: identity_data. The identity is the identity you pass on through options, if none is set the id of your starbox element will be used. If it doesn't have an id, the id 'starbox_#nr', where #nr auto increments, will be automatically added to the element. Once the form is posted you will know what got rated by inspecting the POST or GET vars, depending on how you setup your form. In Php for example:

$_POST('starbox_1_rated');

Page 9: Ajax Imp Codes

The parameters you can access are: rated, average, max and total.

Using Ajax

Let's say you wanted to save all Starboxes using one function. This can be done by observing the document for the event 'starbox:rated'. The following code shows this and goes into the header.

// observing all starboxesdocument.observe('starbox:rated', saveStar);

// observe just onedocument.observe('dom:loaded', function() { // once the DOM is loaded $('id').observe('starbox:rated', saveStar);});

Prototypes 'dom:loaded' is required in this case for $('id').observe() to work, since $('id') is only available after the DOM is loaded. Alternatively you could add the observe code right below the Starbox element itself inside a <script> tag, but the 'dom:loaded' approach will help to keep all your javascript in the same place. The function saveStar will now be called each time a starbox is clicked, below is an example of a possible implementation of that function.

function saveStar(event) { new Ajax.Request('savestar.php', { parameters: event.memo, onComplete: function() { ... } );}

Prototypes Ajax.Request is used to handle the saving part. A nice feature of Starbox is that event.memo holds all the important information: rated, identity, average, max and total. event.memo.rated for example holds the rating that was clicked. Ajax.Request has the option to send along parameters as an object or a querystring. Since event.memo is an object we can simply put it in as parameters.

More on Ajax.Request: http://www.prototypejs.org/api/ajax/request/More on the options you can use: http://www.prototypejs.org/api/ajax/options/

In this case the back-end is done by PHP, so you should be able to use $_POST values like $_POST('identity') and $_POST('rated') to get your rating and complete the database save. If you are not sure how this is done, Google should be able to help with that. In the case of PHP and MySQL, a search for 'ajax save prototype php mysql' should give you enough to get started.

How can I use onRate to save the rating?

Page 10: Ajax Imp Codes

An alternative to using Prototype's custom events is using the onRate callback. The prefered way to handle a post is by using the custom events as described above, this will keep your code clean because onRate doesn't have to be set for each individual Starbox. Should you find the onRate method easier you can use it like this:

function myOnRate(element, memo) = { new Ajax.Request('savestar.php', { parameters: memo, onComplete: function() { ... } );}

Then below your starbox element or preferably in the header using the dom:loaded event as described before, you place the following.

new Starbox('starbox1', 5, { onRate: myOnRate });How can I use the custom events?

Custom events can be used to get more control and handle the rating. You can use the custom events starbox:rated, starbox:changed and starbox:left. Below are examples of each of those. I've also commented the source of this page, it's a good idea to have a look at it, should you require more examples.

document.observe('starbox:rated', function(event) { // event.memo holds important information like event.memo.rated var memo = ''; for(var i in event.memo) memo += i + ' : ' + event.memo[i] + '\n'; alert(memo);

// should you ever need the starbox element itself, use Event#findElement: new Effect.Pulsate(event.findElement('.starbox'));});

$('mystarbox').observe('starbox:changed', function(event) { // this event triggers when hovering stars event.findElement('.starbox').down('.indicator').update(event.memo.rating);});

$('mystarbox').observe('starbox:left', function(event) { new Effect.Shake(event.findElement('.starbox'));});

License

Permission to use Starbox on your domain is required and can be obtained by paying a small fee. For non-commercial domains this will allow you to use Starbox under a

Page 11: Ajax Imp Codes

Creative Commons by-nc-nd License. When you get permission for a commercial domain you may use Starbox under the terms of the Creative Commons by-nd License.

Non-Commercial

Single domain

A small fee is required for non-commercial use.

Non-Commercial

Unlimited

Get permission to use Starbox and future updates on all the non-commercial websites you develop in the future, at no further cost.

Commercial

Single domain

This will give you permission to use Starbox on a single commercial domain.

When is my website considered commercial?

o Commercial

Unlimited

With unlimited permission you are allowed to use Starbox and all future updates on any commercial website you develop in the future, at no further cost.

Download

Download : Starbox 1.1.1

Page 12: Ajax Imp Codes

Note: When updating, make sure to replace all files.

Changelog

Showing the latest changelog entries

*1.1.1* (August 5-2008)

* Image path can now be an absolute url starting with 'http(s)://' or '/'.

Show extra changelog entries

Contact

Use the Starbox Forum for support related questions, feedback, feature requests and bug reports.

For anything non-support related you can contact me at [email protected]. Please use the forum to get support.

rating, stars, prototype, scriptaculous, ajax, javascript, web2.0 Creative Commons by-nc-

Ajax Tabs Content Script (v 2.2)

Author: Dynamic Drive

Note: Updated April 8th, 08 to version 2.2. Adds support for expanding a tab via a link on another page and using a URL parameter. Only .js file changed from v2.1

Description: This is a versatile Ajax Tabs Content script that lets you display content pulled from external files inside a DIV and organized via CSS tabs. A fully unobtrusive, CSS and HTML based script, it supports practical features such as persistence of the active tab (ie: when page is reloaded), an "IFRAME" mode, a "slideshow" mode, ability to expand/contract arbitrary DIVs on the page at the same time, nested tabs, and much more. We got our inspiration for this script from Yahoo's homepage, which employs such a concept to show news in an organized fashion.

Here's a quick outline of the script features:

Fetch and display an external page (from the same domain) inside a container when a tab is clicked on via Ajax.

Page 13: Ajax Imp Codes

(v 2.0) Apart from Ajax, an external page can also be fetched and displayed via the IFRAME element instead. This is useful for external pages that either contain JavaScript/ CSS code that doesn't run properly when fetched via Ajax, or the page is from an outside domain.

Add a "default" content inside the container to either be shown while no tabs are selected, or to be associated with a specific tab. The default content is added inline on the page and not fetched via Ajax, to avoid unnecessary fetching of external pages.

Supports session only persistence, so the last tab user clicked on is remembered if he/she returns to the page within the same browser session.

(v 2.0) Supports auto mode, in which script automatically cycles through and selects each tab periodically until a tab is explicitly selected.

(v 2.0) Ability to also expand/contract arbitrary DIVs on the page as the tabbed content is expanded/ contracted.

(v 2.0) Ability to dynamically select a tab either based on its position within its peers, or its ID attribute.

(v 2.1) Ability to dynamically cycle forward/back between tabs. Create a "Next" and "Back" link for users to move between tabs, for example.

(v 2.2) A link from another page linking to the target page can select a tab on the later when loaded, via the URL parameter string ((ie: http://mysite.com/tabcontent.htm?tabinterfaceid=0).

(v 2.0) Ability to directly load a different external page into the content container, either via Ajax or IFRAME.

(v 2.0) Ability to set where the CSS class "selected" get assigned when a tab is clicked on- either on the tab link itself (its "a" element), or its parent instead (ie: "li" element). This makes the script adaptable to both CSS Tabs that are styled at the "A" level itself, or its parent container instead.

(v 2.0) Supports nested Ajax Tabs! In other words, you can have an external page fetched via Ajax contain in itself Ajax Tabs that show their own contents when clicked on as well. This is made possible using the "onajaxpageload" custom event handler (see documentation).

Supports multiple Ajax Tabs Contents on the same page.

Fully unobtrusive, search engine friendly design. For search engines or browsers with JavaScript disabled, the external contents will just load as actual pages (instead of via Ajax).

As you can see, this Ajax Tabs Content script was designed to be much more than look pretty, but usable.

Page 14: Ajax Imp Codes

Reminder: Due to security limitations, the external pages loaded via each tab using Ajax must reside on the same domain as the script itself. This limitation doesn't apply if you use the "IFRAME" option to fetch and show the external page instead.

Demos:

Directions

To add this script to your page, just download "ajaxtabscontent.zip", and refer to "demo.htm" inside for the full source code to the 3 demos you see above:

ajaxtabscontent.zip (consists of the below files):1. demo.htm

2. ajaxtabs.css

3. ajaxtabs.js

4. loading.gif

5. shade.gif , shadeactive.gif, indentbg.gif, indentbg2.gif

6. Demo files: external1.htm, external2.htm, external3.htm, external4.htm, and external5.htm

Setting up the script on your page- basic usageLets see in detail now how to set up this script on your page. After having added the .js and .css file references to the HEAD section of your page, as seen in demo.htm, proceed with the following:

Step 1: Define the HTML for the Tabs themselves. This can be a fancy CSS menu, or even just a DIV tag with a bunch of links inside. Lets use the former:

<ul id="countrytabs" class="shadetabs"><li><a href="#" class="selected" rel="#default">Tab 1</a></li><li><a href="external2.htm" rel="countrycontainer">Tab 2</a></li><li><a href="external3.htm" rel="countrycontainer">Tab 3</a></li><li><a href="external4.htm" rel="#iframe">Tab 4</a></li><li><a href="http://www.dynamicdrive.com">Dynamic Drive</a></li></ul>

Page 15: Ajax Imp Codes

The parts in red are significant, regardless of how you define your tabs:

1. id="countrytabs": Give the main container of your tab links a unique ID (ie: "countrytabs"). All links ("A" elements) within this container will be scanned by the script for special meaning.

2. rel="#default|containerid|#iframe": For each tab link that should reveal content when clicked on, add a "rel" attribute inside its link tag with one of three possible values: "#default", id_of_container_div, or "#iframe". This in combination with the link's href attribute determines what external file to fetch, and how to display it. Most commonly you'll be using containerid, which corresponds to the ID of the container DIV on the page in which to load the Ajax fetched content (see Step 2 below). "#default" and "#iframe" on the other hand are both special keywords. "#default" causes the tab to show no external content but instead what's embedded directly inside the container DIV, while #iframe causes the tab to show its content inside an IFRAME tag instead of via Ajax.

3. rev="divid1, divid2, etc": For each tab link, you can also insert a rev attribute to simultaneously toggle the visibility of arbitrary DIVs on the page. See example #1 in the documentation page for more info.

4. class="selected": If you wish a certain tab to be selected by default when the page loads, give the tab in question a class="selected" assignment. By default it should be added inside the link itself ("A"). However, the script can also be told to look for such as class in the link's parent container instead (in this case, "LI"). This is useful depending on how the CSS for your tabs are structured. See the documentation page for more info.

5. A tab can also just act as a regular link, with the absence of the "rel" attribute (ie: the "Dynamic Drive" tab at the very end).

There is an additional attribute you can use, the "rev" attribute, to also expand/contract arbitrary DIVs outside the Tab interface. See the documentation below for details.

Step 2: Define a Content container DIV that will house the display of the external pages specified in the tabs above:

<div id="countrydivcontainer" style="border:1px solid gray; width:450px; margin-bottom: 1em; padding: 10px">//Optional default content here.</div>

The only required portion is the DIV itself with a unique ID assigned as highlighted in red. The content "//Optional default content here" that's added inside the DIV, is, well, optional. Define it if you wish a certain tab to show this content instead of external content fetched via Ajax or IFRAME. It's useful as the content for the tab selected by default when the page loads, to cut down on the trips the script has to take to fetch files

Page 16: Ajax Imp Codes

from the server. To associate a tab with the default content of the container DIV btw, you would use the declaration rel="#default" inside the tab's link.

Step 3: With your Tabs and the container DIV both defined, it's now time to activate the script, by calling ddajaxtabs() with the desired settings:

<script type="text/javascript">

var countries=new ddajaxtabs("countrytabs", "countrydivcontainer")countries.setpersist(true)countries.setselectedClassTarget("link") //"link" or "linkparent"countries.init()

</script>

The first line tells the script the IDs of both your CSS tabs container and content container, in that order, with the variable "countries" being an arbitrary but unique identifier variable. The second line toggles the persistence of the tabs' state, whether or not a clicked on tab should be remembered and recalled upon the user's return (within the same browser session). The 3rd line tells the script whether to look for class="selected" within the tab link ("A") itself, or its parent container instead (ie: "LI"). What value to use depends on where you will be inserting the class="selected" attribute inside a tab. Lastly, the 4th line initializes everything.

And that's it for setting up the script in its basic form. However, you'll want to also learn how to expand/contract arbitrary DIVs on the page at the same time a tab is selected, plus how to get the tabs to automatically rotate like a slideshow. That's what the documentation below is for!

Adding default content to Ajax Tabs

While you can certainly configure the script so that every tab loads an external page, you might as well have a particular tab show content that already exists within the content container:

<div id="countrydivcontainer" style="border:1px solid gray; width:450px; margin-bottom: 1em; padding: 10px">//Optional default content here.</div>

Any HTML added inside the DIV above is the default content, and can either be shown if the script is not set to select any tab automatically, or if associated with a certain tab, so clicking that tabs shows this content. For the later, to associate the default content with a tab, just use the keyword "#default" instead of the ID of the container DIV inside the

Page 17: Ajax Imp Codes

tab link's "rel" attribute:

<li><a href="#" rel="#default">Tab 1</a></li>

Syntax for specifying an external page to load

When specifying a tab to load an external page, either via Ajax or IFRAME, the path to the page is specified in the tab link's "href" attribute:

<li><a href="external.htm" rel="countrycontainer">Tab 2</a></li>

This assumes external.htm is in the same directory as where the Ajax Tabs script is. You use an absolute URL to the external page as well:

<li><a href="http://www.mysite.com/dir/external.htm" rel="countrycontainer">DHTML</a></li>

For Ajax fetched pages, You cannot, however, specify a URL that's outside your server's domain, such as "http://www.google.com/page.htm', as Ajax security dictates that the calling page and page to be fetched via Ajax must be from the same domain. This limitation doesn't apply to the IFRAME method.

This convention for specifying the page to load means the script downgrades 100% with JS disabled browsers and search engines, allowing them to load the links as normal pages.

Turning on slideshow mode

You can have the tabs within your Ajax Tabs Content automatically rotate every x seconds until a user explicitly clicks on a tab. To enable "slideshow mode" on your Tab Content, just pass in an integer when calling instance.init() to initialize your script:

<script type="text/javascript">

var myflowers=new ddajaxtabs("flowertabs", "flowerdivcontainer")myflowers.setpersist(true)myflowers.setselectedClassTarget("link") //"link" or "linkparent"myflowers.init(3000)

</script>

Notice the integer in red, which is in units of milliseconds. With one defined, the script will rotate through the tabs every x milliseconds (so 3000=3 seconds).

Expanding/ Contracting arbitrary DIVs on the page when a tab is

Page 18: Ajax Imp Codes

selected

You already know that a tab can fetch external content either via Ajax or IFRAME via the "rel" attribute. However, you can in fact take this one step further, and also have the same tab manipulate the visibility of arbitrary DIVs on the main page itself! This is done using the "rev" attribute, and setting them to the ID(s) of the arbitrary DIVs on the page to also expand/contract. See example #1 in the documentation page for more info.

On the next page, we look in detail the three methods at your disposal to dynamically select a tab or load an external page into the Content Container from anywhere on your page.

Table Of Contents

This script consists of an index page plus a supplementary page:

Script Index Page Dynamically selecting a tab/ loading an external page updated for v2.2

Nesting ajax tabs

Ajax Tabs Content documentation

Copyright © 1998-2008 Dynamic Drive. Please read Terms Of Use

Home

IntroductionSometimes, when we are building websites and web applications, we need a percentage bar / progress bar to show the progress of a specific task. However, it is very difficult to find a working and easy solution without using Flash. Therefore WebAppers have created a simple Javascript based Percentage Bar / Progress Bar which is inspired by Bare Naked App. Bare Naked App taught us how to display Percentage Bar with 2 images only by using CSS. And then I used a little bit of Javascript to make it more interactive. You can use it anywhere you can think of. Use your Imagination, I am sure you will find it useful somewhere.

Go Back to Original Article

Page 19: Ajax Imp Codes

DemoProgram Efficiency

15% Empty Bar

Website Projects Progress

100% Minus 5%

Weight Lost Progress

50% Get Current %

Upload Progress Bar

80% Get Cur Documentation

What is AJAX?

AJAX, an acronym for Asynchronous JavaScript and XML, is a web development technique for creating interactive web applications. The intent is to make web pages feel more responsive by exchanging small amounts of data with the server behind the scenes, so that the entire web page does not have to be reloaded each time the user makes a change. This is meant to increase the web page's interactivity, speed, and usability.

Using the XmlHttp Object

An XmlHttp object can be created like this:

Collapse

<script language="javascript"> //Global XMLHTTP Request objectvar XmlHttp;

//Creating and setting the instance of appropriate XMLHTTP Request object to //a "XmlHttp" variable function CreateXmlHttp(){ //Creating object of XMLHTTP in IE try { XmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) {

Page 20: Ajax Imp Codes

try { XmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch(oc) { XmlHttp = null; } } //Creating object of XMLHTTP in Mozilla and Safari if(!XmlHttp && typeof XMLHttpRequest != "undefined") { XmlHttp = new XMLHttpRequest(); }}</script>

Send the request to the server side page

We can send a request to the server page to retrieve the data from the server through the XmlHttp object.

var requestUrl = "WebForm2.aspx" + "?SelectedCountry=" + (selectedCountry); CreateXmlHttp(); // If browser supports XMLHTTPRequest object if(XmlHttp) { //Setting the event handler for the response XmlHttp.onreadystatechange = HandleResponse; //Initializes the request object with GET (METHOD of posting), //Request URL and sets the request as asynchronous. XmlHttp.open("GET", requestUrl, true); //Sends the request to server XmlHttp.send(null); }

The above code explains how to send a request to webpage2.aspx with the request object collection. This collection contains the selected country itself.

Process the client request

When the request is recieved on the server side, the server page executes the code and gives the response through the XmlHttp object:

Dim xList As XmlNodeListDim xNode As XmlNodeDim Str As StringxmlDoc.Load(Server.MapPath("CountriesAndStates.xml"))

Page 21: Ajax Imp Codes

Dim Country As String = Request.QueryString("SelectedCountry")Dim query As String = ("/countries/country[@name='" & country & "']")xlist = xmlDoc.SelectNodes(query)

Response.Clear() For Each xNode In xList If xNode.HasChildNodes = True Then For Each xN As XmlNode In xNode.ChildNodes Str &= xN.InnerText & "-" Next End IfNext

Response.Clear()Response.ContentType = "text/xml"Response.Write(str)Response.End()

Using the XmlHttp object to retrieve the data

Recieving the response from the server page can be done like this:

The valid list of XMLHttpRequest ready states is listed in the following table:

Value Description

0 Uninitialized

1 Loading

2 Loaded

3 Interactive

4 Complete

The list of status codes for the HTTP status is given below:

Page 22: Ajax Imp Codes

1xx Informational

Request received, continuing process.

100: Continue 101: Switching Protocols

2xx Success

The action was successfully received, understood, and accepted.

200: OK 201: Created

202: Accepted

203: Non-Authoritative Information

204: No Content

205: Reset Content

206: Partial Content

207: Multi-Status

3xx Redirection

The client must take additional action to complete the request.

300: Multiple Choices 301: Moved Permanently. This and all future requests should be directed to

another URI.

302: Found this the most popular redirect code, but also an example of industrial practice contradicting the standard. HTTP/1.0 specification (RFC 1945) required the client to perform a temporary redirect (the original describing phrase was "Moved Temporarily"), but popular browsers implemented it as a 303 See Other. Therefore, HTTP/1.1 added status codes 303 and 307 to disambiguate between the two behaviors. However, majority of web applications and frameworks still use the 302 status code as if it were the 303.

303: See Other (since HTTP/1.1). The response to the request can be found under another URI using a GET method.

304: Not Modified

305: Use Proxy (since HTTP/1.1). Many HTTP clients (such as Mozilla and Internet Explorer) don't correctly handle responses with this status code.

306 is no longer used, but reserved. Was used for 'Switch Proxy'.

Page 23: Ajax Imp Codes

307: Temporary Redirect (since HTTP/1.1). In this occasion, the request should be repeated with another URI, but future requests can still be directed to the original URI. In contrast to 303, the original POST request must be repeated with another POST request.

4xx Client Error

The request contains bad syntax or cannot be fulfilled.

400: Bad Request 401: Unauthorized. Similar to 403/Forbidden, but specifically for use when

authentication is possible but has failed or not yet been provided. See basic authentication scheme and digest access authentication.

402: Payment Required. The original intention was that this code might be used as part of some form of digital cash/micropayment scheme, but that has not happened, and this code has never been used.

403: Forbidden

404: Not Found

405: Method Not Allowed

406: Not Acceptable

407: Proxy Authentication Required

408: Request Timeout

409: Conflict

410: Gone

411: Length Required

412: Precondition Failed

413: Request Entity Too Large

414: Request-URI Too Long

415: Unsupported Media Type

416: Requested Range Not Satisfiable

417: Expectation Failed

449: Retry With A Microsoft extension: The request should be retried after doing the appropriate action.

5xx Server Error

The server failed to fulfill an apparently valid request.

Page 24: Ajax Imp Codes

500: Internal Server Error 501: Not Implemented

502: Bad Gateway

503: Service Unavailable

504: Gateway Timeout

505: HTTP Version Not Supported

509: Bandwidth Limit Exceeded. This status code, while used by many servers, is not an official HTTP status code.

if(XmlHttp.readyState == 4) { // To make sure valid response is received from the server, // 200 means response received is OK if(XmlHttp.status == 200) { ClearAndSetStateListItems(XmlHttp.responseText); } else { alert("There was a problem retrieving data from the server." ); } }

There are two types of XmlHttp responses for rectrieving the response.

1. responseText 2. responseXML

Show the states in the dropdownbox

The responseText is split using the split function and the response is assigned to an array.

Then, the array values are added in the dropdown list.

var stateList = document.getElementById("stateList"); //Clears the state combo box contents. for (var count = stateList.options.length-1; count >-1; count--) { stateList.options[count] = null; }

var stateNodes = countryNode.split("-"); //window.alert(stateNodes) var textValue; var optionItem; //Add new states list to the state combo box. for (var count = 0; count < stateNodes.length; count++) {

Page 25: Ajax Imp Codes

textValue = (stateNodes[count]); optionItem = new Option( textValue, textValue, false, false); //window.alert(textValue); //stateList.appendChild(textValue); stateList.options[stateList.length] = optionItem; }

Introduction

This is an AJAX AutoSuggest ASP.NET textbox I've created a while ago. It is built on top of the Anthem.NET library.

Background

When building enterprise web applications, we often need to let the user select one item from a large list of records. For instance, on an order entry form, the user must be able to select the customer from a large list of customers. For performance reasons, it would be insane to just load a DropDownList with 50000 items. The other alternative would be to open another form where the user would be able to search and select the desired

Page 26: Ajax Imp Codes

customer. I've used this approach before, but the users usually found it very annoying and were constantly demanding a better solution.

Solution

The AJAX boom made it an easy problem to solve. An AutoSuggest textbox, where the user would type a part of the desired customer name and the control would show the matches, would fit perfectly here. Yet, I couldn't find one that would completely fill my needs. I needed an AutoSuggest textbox with the following features:

Built-in validation Template-based content

Ability to bind to all sorts of objects (collection, datatables, etc)

Ability to work like a DropDownList

Smooth integration with Anthem.NET

Ability to show a header

No need to call webservices

The Control

This custom control is based on the Anthem library. I decided to use Anthem because at that time I was already using it on my projects. The Atlas Project was not mature enough and Anthem seemed much easier and more powerful. The Anthem library now has an official AutoSuggest control, but I haven't checked it out yet. If you are not familiar with Anthem.NET yet, I encourage you to check it out. It's pretty simple and works great. The JavaScript OO model was based on another free AutoSuggest control that I found on this web site. I found it pretty nice, but it was missing some functionality I needed.

Setting Up

To use this AutoSuggest control, you will need to reference both the Anthem.dll and Anthem.AutoSuggest.dll in your project. The download contains these DLLs, the AutoSuggest source code and an example project source code.

Using the Code

The first thing you need to do is to add the control to your page. This can be done through drag and drop or by writing the tags directly into the ASPX source file. Since I didn't add any relevant design-time support, I think you'd better stick with the ASPX source code. In this example we are using the AutoSuggest control to display the names of various bands and the user must select his favorite one.

Page 27: Ajax Imp Codes

<Anthem:AutoSuggestBox runat="server" ID="asbFavoriteBand" DataKeyField="ID" TextBoxDisplayField="Name" AutoCallBack="true" ItemNotFoundMessage="Item not found!" > <itemtemplate> <%# ((Band)Container.DataItem).Name %> </ItemTemplate></Anthem:AutoSuggestBox>

I think most of the property names are self-explanatory. I encourage you to go through the properties and play with them. For those unfamiliar with the Anthem.NET library, the AutoCallBack attribute tells that after the selected value has changed, the control will trigger a callback to the server. It's equivalent to the AutoPostBack property of the regular ASP.NET controls. Notice that you can use the ItemTemplate in the same manner in which you use it with the Repeater, DataList or DataGrid controls. The DataKeyField property tells the control which field it will use to set the SelectedValue property.

After adding the control to the page, you should set up the event handlers. The most important event you should handle is the TextChanged event. This is where you are going to fill the suggested list. Another important event is the SelectedValueChanged. This event is fired whenever you change the current value. To wire up these handlers, you can write the following code in the OnInit method:

protected override void OnInit(EventArgs e){ base.OnInit(e); this.asbFavoriteBand.TextChanged += new Anthem.AutoSuggestBox.TextChangedEventHandler( asbFavoriteBand_TextChanged);

this.asbFavoriteBand.SelectedValueChanged += new Anthem.AutoSuggestBox.SelectedValueChangedHandler( asbFavoriteBand_SelectedValueChanged);}

Here's the code to handle the TextChanged event:

void asbFavoriteBand_TextChanged(object source, Anthem.AutoSuggestEventArgs e){ //Creates a dataview from a datatable DataView dv = new DataView(_dtBands);

//Filters the datatable based on the CurrentText property dv.RowFilter = string.Format("BandName LIKE '%{0}%'", e.CurrentText);

//Sets the dataview as the control's datasource asbFavoriteBand.DataSource = dv; asbFavoriteBand.DataBind();}

Page 28: Ajax Imp Codes

In the snippet above, you can use any data source on the AutoSuggest control. Usually you would query the database for the result set. It's when you call the DataBind method that the suggested list appears on the screen.

Points of Interest

There are, definitely, some nice aspects of this control that demand a closer look at how .NET controls work, like using embedded web resources (images, JavaScript and CSS files), supporting template based content, triggering events and handling the JavaScript integration.

Object-Oriented JavaScript is also worth a look. It really makes things easier.

Page 29: Ajax Imp Codes

display(elementId, percentage, colorCode)

Display the Percentage Bar

int colorCode: 1 = Green

int colorCode: 2 = Yellow

int colorCode: 3 = Orange

int colorCode: 4 = Red

emptyProgress(elementId)

Empty the Percentage Bar by setting 0%

plus(elementId, percentage)

Increment the Percentage Bar by the specified percentage

minus(elementId, percentage)

Decrement the Percentage Bar by the specified percentage

setProgress(elementId, percentage)

Set the Percentage Bar with the specified percentage

fillProgress(elementId, percentage)

Fill up the Percentage Bar with the specified percentage

LicenseThis library is licensed under Creative Commons license, so you can use it for anything you like, as long as you include the copyright notice.

Loading XML into a page with xmlHttpRequest

18 Jan 2005 21:48 - (6) comments

Page 30: Ajax Imp Codes

Using javascript to talk to the server can be useful for complex applications that need to make multiple small requests to the server and make it fast. By doing this you can keep most of the logic on the server where it belongs. So it can help prevent the complex client anti-pattern (even worse ishaving basicaly the same code on the client and server side).

I dabbled a little with a xmlhttprequest demo.

In the onclick I call the showFeed function and pass the xml and xsl files as arguments. This is what showFeed looks like:

function showFeed(xmlUrl, xslUrl) {

var feed = document.getElementById('feed');

//clear feed div

while(feed.hasChildNodes()){

feed.removeChild(feed.childNodes[0]);

}

//append new htmlfragment

feed.appendChild(getHtmlFragment(xmlUrl, xslUrl));

}

First it finds the div where the new content will be added. I called it 'feed'. Then it removes all the old content and adds the new content by calling getHtmlFragment.

Page 31: Ajax Imp Codes

function getHtmlFragment(xmlUrl, xslUrl) {

var xslStylesheet;

var xsltProcessor = new XSLTProcessor();

//load the xml file

var xmlSource = getResponseXml(xmlUrl).responseXML;

//load the xsl file into the xslt Processor

xslStylesheet = getResponseXml(xslUrl).responseXML;

xsltProcessor.importStylesheet(xslStylesheet);

return xsltProcessor.transformToFragment(xmlSource, document);

}

function getResponseXml(xmlUrl) {

var xmlHttp = new XMLHttpRequest();

xmlHttp.open("GET", xmlUrl, false);

xmlHttp.send(null);

return xmlHttp;

}

Page 32: Ajax Imp Codes

The function getHtmlFragment loads all XML content by calling getResponseXml and uses xsltProcessor to transform the XML to XHTML.

Using xmlHttpRequest() seems to be all the rage and we'll be seeing a lot more examples.

Comments

Add a TITLE element and a HTML 4.0 DOCTYPE ;-)

On 18 Jan 23:54 by Anne

Done! :)

On 19 Jan 10:04 by Petrik

Nice demo. You could make a whole feed-reader in an HTML page with this: keep the blogroll in an XML file, load it, then load the feeds it points to.

One problem is that the browser seems to hang until the feed is loaded. This is a known problem with a known solution, the 'proper' way to send a request is demonstrated at http://jibbering.com/2002/4/httprequest.html ...All XMLHttpRequest demos should use async mode and the onreadystatechange property.

(Btw, the comment preview seems to escape apostrophes without reason.)

On 19 Jan 11:26 by Rahul

And line breaks aren't converted automatically?

On 19 Jan 11:27 by Rahul

Thanks Rahul! I fixed both.

On 19 Jan 14:44 by Petrik

As you are transforming the data on the client you could make use of the ResponseHeader.

var modded = xmlhttp.getResponseHeader("Last-Modified")

That way you can check the requested data has not changed and prevent an unnecessary download and all the bandwidth,code,checking status etc. that goes with fetching the data from the server for each transform.

Page 33: Ajax Imp Codes

The standard ASP.NET calendar control while useful, does not have the hooks to customize title date displays. Furthermore, the control model is not flexible enough to allow extension through sub-classing. I have implemented an AJAX control extender (CalendarUIExtender) that exposes a rich API for fine-grained control over title date and day header displays. Unlike extenders in AjaxControlToolkit, this extender's target control is the standard ASP.NET Calendar control and it is intended to enhance the UI capabilities of the Calendar control. It features bit flag enumerations with the ability to turn specific date components on or off, customization of the order of rendering of date components, custom prefix and suffix, auto-generation of date suffix (such as 1st, 2nd, 12th), auto-formatting, date display behavior (today's date in current month view, today's date always, selected date, etc.), custom day headers and so on.

The final date output is computed from bitwise specifications using the DateExpressionBuilder utility class. DateExpressionBuilder is the heart of the formatting engine which uses an algorithm that I came up with along with a series of utility functions, to compute a custom date format pattern that is used as an argument to DateTime.ToString. The CalendarUIExtender control implements a JavaScript prototype that handles client-server property synchronization and also client side rendering using DHTML and JavaScript. The output generated by the extender is delivered to the JavaScript prototype which parses the HTML output generated by ASP.NET Calendar and substitutes specific regions of the output to render customized date title and day header specifications. Please refer to the section on rendering for details.

The extender control features a rich UI designer that enables control configuration through region-specific action lists. It also features smart tag functionality, so that the user can preview the rendered output in the Visual Studio design view.

Usage

The snippet below shows one of the ways to customize day headers and title date rendering. However, it is preferable to use the rich design time rendering capabilities of the CalendarUIExtender's designer to visually generate these settings.

<cc1:CalendarUIExtender ID="CalendarUIExtender1" runat="server" EnableViewState="true" TargetControlID="calTest" TitleDateDisplayBehaviour="UserDefinedPrefixSuffixBehaviour" TitleDateDisplayOrder="DayOfWeek_Date_Month_Year" TitleDateValueBehaviour="TodayAlways" TitleDateDayOfWeekSuffix=", " TitleDateYearPrefix=", " DayHeaderFormat ="Custom" CustomDayHeaders="Sun,M,Tu,W,Th,F,Sat" ></cc1:CalendarUIExtender>

Title Date and Day Header Rendering Customization

Page 34: Ajax Imp Codes

Title Date and Day Header Rendering Customization

CalendarUIExtender implements a WYSIWYG designer that supports smart tags, regions and region-specific action lists. The following is a set of screenshots that show the extender control in action.

Control Rendering in the Visual Studio Designer

Page 35: Ajax Imp Codes

Control Rendering in the Browser

Control Rendering in the Browser

Page 36: Ajax Imp Codes

Custom User Phrases can be Combined with Auto-Generated Date Suffixes (e.g. 12th, 22nd)

Structure of the Calendar Extender Control

Structure of the Calendar Extender Control

The code and logic of this control and its utilities is complex and extensive. I don't intend to write an elaborate article on this. Please refer to the source code if you are curious about the working of components under the hood.

Page 37: Ajax Imp Codes

DateDisplaySpec is a bitwise enumeration (Flags enum) that can be XORed to turn specific bits on or off, along with other typical bitwise operations such as OR.

Page 38: Ajax Imp Codes

The following classes implement rich Visual Studio designer preview features (context menu with smart tags and region specific action lists).

Page 39: Ajax Imp Codes

Behavior Modes

Title Date behavior modes:

public enum DateDisplayBehaviour{ ASPNetCalendarSetting, DefaultPrefixSuffixBehaviour, UserDefinedPrefixSuffixBehaviour}

public enum DateValue{ ASPNetCalendarSetting, TodayAlways, TodayOnlyInCurrentMonth, SelectedDate, VisibleDate}

public enum DateDisplayOrder{ DayOfWeek_Month_Date_Year, // Sunday Jan 23 2007 DayOfWeek_Date_Month_Year, // Sunday 23rd Jan 2007 Year_Month_Date_DayOfWeek // 2007 Jan 23 Sunday}

Page 40: Ajax Imp Codes

Day Header behavior modes: format of day header names. When the format value is Custom, the TitleDayHeader property is set to a comma-separated list of header names.

public enum DayHeaderFormat{ ASPNetCalendarSetting, OneLetterDay, TwoLetterDay, ThreeLetterDay, FullName, Custom // allows custom names for day headers}

Bitwise flags allow fine-grained control over individual attributes of the title date and day header display.

[Flags]public enum DateDisplaySpec : int{ None = 0, YearPrefix = 0x01, YearSuffix = YearPrefix<<1, Year4Digits = YearSuffix<<1, Year2Digits = Year4Digits<<1, MonthPrefix = Year2Digits<<1, MonthSuffix = MonthPrefix<<1, MonthNumericAnyDigits = MonthSuffix<<1, MonthNumeric2Digits = MonthNumericAnyDigits<<1, MonthFullWord = MonthNumeric2Digits<<1, Month3LetterAbbreviation = MonthFullWord<<1, DatePrefix = Month3LetterAbbreviation<<1, DateSuffix = DatePrefix<<1, DateSuffix2Letter = DateSuffix<<1, DateAnyDigits = DateSuffix2Letter<<1, Date2Digit = DateAnyDigits<<1, DayOfWeekPrefix = Date2Digit<<1, DayOfWeekSuffix = DayOfWeekPrefix<<1, DayOfWeekNumeric = DayOfWeekSuffix<<1, DayOfWeekFullWord = DayOfWeekNumeric<<1, DayOfWeek3LetterAbbreviation = DayOfWeekFullWord<<1}

Layered Rendering1. The ASP.NET calendar control renders table markup. 2. The extender's JavaScript prototype parses the target ASP.NET calendar

control's HTML output and replaces the content of the title date cell and the 7 day header cells. If the extender is configured to mimic ASP.NET calendar behavior, then the prototype rendering is by-passed. This allows the standard calendar output to be rendered as-is.

Page 41: Ajax Imp Codes

Differences w.r.t. AjaxControlToolkit CalendarExtender

Header CalendarExtender My control

Use case

Meant to be a pop-up calendar with an event-driven trigger to show or hide the calendar.

Meant to be an always-on calendar on a webpage.

Functionality Implements a date picker functionality.

Does not implement a behavior that's different from the ASP.NET calendar control. It's meant to be a UI enhancer. However, it adds some additional behavior to the calendar control that is UI-specific.

Target Targets another control (textbox, drop-down, etc).

Targets the ASP.NET calendar in the same naming container (by default).

Model

A JavaScript rewrite of the ASP.NET calendar functionality, including model (SelectedDate, VisibleDate, style, etc). The prototype implements all the calendar logic.

Not meant to be a JavaScript calendar (it can always be AJAX-ified by wrapping the ASP.NET calendar in an update panel).

Reuses the ASP.NET calendar model as well as implementation and injects its model and implementation transparently at runtime.

Styles

Calendar styles are set in style sheet classes. Not trivial unless the developer is aware of advanced HTML style concepts.

Reuses the ASP.NET calendar style properties. Developer can easily define styles through the ASP.NET calendar control designer.

Designer preview

Designer does not render design time preview in Visual Studio.

The extender has a designer that renders a preview of title date and calendar day headers by applying styles defined for the ASP.NET calendar control.

The designer implements regions and region-specific smart tags.

When the extender is in mode, the designer renders ASP.NET calendar day headers using

Page 42: Ajax Imp Codes

Header CalendarExtender My control

reflection.

Title Date Format

The Format property is defined using DateTime format grammar. There is no preview available at design time. It is not simple to the average developer.

Defines bit flag enumeration and properties for each date component.

Enables out-of-the-box coarse-grained, as well as fine-grained, configuration.

The designer preview in Visual Studio makes it easy to configure.

The DateExpressionBuilder class is the engine that computes the final result by translating user-defined and automated behavior into DateTime format specs.

Adding custom phrases is not simple for the average developer.

Can be done in the designer without requiring knowledge of DateTime format specs for custom phrases.

Auto-generates date suffixes (if enabled). For ex. 21st, 11th, 22nd, 3rd, 13th

Dynamic title date

Title date is static based on the Format property

Allows dynamic title date behavior:

ASPNetCalendarSetting TodayAlways

TodayOnlyInCurrentMonth (when user shifts to a different month, it displays visible date in the format specified; otherwise, today's date)

SelectedDate

VisibleDate

Day Headers

Does not allow day header customization

Allows single letter, 2-letter, 3-letter, full name, as well as custom names for day of week headers in the day header row.

Page 43: Ajax Imp Codes

Gmail like file upload button

Introduction

This is an inherited button control which can perform file upload like in gmail manner. The button uses the inherited IFRAME technique to avoid full page rendering so that user will get a nice experience.

Background

I have searched for an article to perform GMail like file upload. It seems that we cannot perform file uploading using AJAX. I got some nice javascript from webtoolkit which was written to operate with PHP. The script uses the hidden IFRAME technique. Here I have created an derived ASP.NET Button control which can perform the trick.

Using the code

To open the project, unzip it and open the file FileUploadControlTest.sln Open the file UploadButton.cs. The OnInit method will register the LoadComplete event, include the javascript which is a web resource (for more information on webresource click here), and sends the onsubmit statement to client.

/// <summary /> /// Basic registration of events /// </summary /> /// protected override void OnInit(EventArgs e) { this.Page.LoadComplete += new EventHandler(Page_LoadComplete); base.OnInit(e); this.Page.ClientScript.RegisterClientScriptInclude(this.GetType(), "ScriptBlock", this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "WebControls.JScripts.AIMScript.js")); string onsubmitstatement = "return AIM.submit(document.forms[0], {'onStart' : " + OnStartScript + ", 'onComplete' : " + OnCompleteScript + "})"; this.Page.ClientScript.RegisterOnSubmitStatement(this.GetType(), "OnSubmitScript", onsubmitstatement); }

The onsubmit script creates a new hidden IFRAME in the dom and sets the target of the form to this IFRAME. So the section the user is seeing will not get redrawn after postback.

Page 44: Ajax Imp Codes

In the Page_LoadComplete event of the page, we will get the FileUpload control filled with the uploaded file. We will call the event handler in the Page_LoadComplete method. The return text after executing the event handler will be returned to the client.

Collapse

/// <summary /> /// After completing page load, call the event handler on page to perform /// operations on uploaded file /// </summary /> /// /// void Page_LoadComplete(object sender, EventArgs e) { if (Page.IsPostBack) { if (this.Parent.FindControl(RelatedFileUploadControlId) != null) { FileUpload fu = this.Parent.FindControl(RelatedFileUploadControlId) as FileUpload; UploadButtonEventArgs args = new UploadButtonEventArgs(fu); UploadButtonEventHandler handler = (UploadButtonEventHandler)Events[EventUploadClickKey]; if (handler != null) { try { WriteTextToClient(handler(this, args)); } catch (System.Threading.ThreadAbortException ex) { // do nothing } catch (Exception ex) { WriteTextToClient("An exception occurred - " + ex.Message); } } else { WriteTextToClient("Handler not registered"); } } } }

Page 45: Ajax Imp Codes

Introduction

In my last article we added a server control property that allows us to take control over how the ListBox responds to mouse wheel events. In this article, we're going to take care of some anomalies and fully enforce browser compatibility for the mouse wheel.

Background

Once again, let's review the requirements checklist we drew out in the second article. Now that we're getting down to the nitty gritty, we're going to break #4 out into 2 separate requirements:

1. It is difficult or impossible to select multiple disparate items at once by using the SHIFT and CONTROL keys because their onkeydown events trigger the scrollbars to be repositioned based on the first item(s) selected. We should read the keyCode of the event and bypass our scrolling code for "meta" keypresses like this.

2. The ability to scroll through the items using a mouse wheel depends on both the browser and version used to load the page. We would like to make mouse scrolling a configurable option supported on all target browsers.

3. The vertical and horizontal scrollbar positions are only preserved across postbacks when the control's HorizontalScrollEnabled property is explicitly set

Page 46: Ajax Imp Codes

to true. We should be able to preserve scroll state event when HorizontalScrollEnabled is false.

4. Our event handling strategy does not fully support Firefox 1.0 because some user interactions which change the scroll position do not execute the _onContainerScroll event handler.

5. If you ever try debugging the _onContainerScroll handler, you'll notice IE can execute it up to four times for a single mouse click or keystroke. Dragging a scrollbar causes my CPU to briefly jump to 30% or higher, depending on how fast I scroll. Updating the hidden field this many times places an unnecessary load on the client computer's processor.

Although it may seem that we've squashed #2, those of you who are keen on Firefox may have noticed the following quirks:

In FF1, when HorizontalScrollEnabled == true and MouseWheelScroll == Enforce, the ListBox does not respond to the mouse wheel while the cursor is positioned over the scrollbars.

In FF1.5 and FF2, when HorizontalScrollEnabled == true and MouseWheelScroll == Prevent, the ListBox does respond to the mouse wheel while the cursor is positioned over the scrollbars.

In FF1, when the mouse wheel is used to scroll, the scroll state is not saved to the hidden field. Incidentally, this is the last outstanding issue for requirement #4.

The first two quirks surfaced because we didn't handle the DIV container's DOMMouseScroll event. We should tackle that issue first because it will ultimately affect the third.

Copy and Paste

Here is the reason why we gave the DIV a _thisPrototype field pointing to the prototype in the last article. Now we already have access to the client control's fields that are needed to compute the new scroll position when the DIV receives the onscroll event. Granted, I could've written the _onContainerMouseWheel code differently than the _onMouseWheel code, since the this reference will always point to the DIV. However, writing it this way gives us an opportunity to consolidate the code into a helper function later.

Collapse

// find this snippet inside if _initializeEvents()// FF doesn't have an onmousewheel eventif (this.get_element().onmousewheel === undefined){ this.get_element().addEventListener( 'DOMMouseScroll', this._onMouseWheel, false);

// register the container's wheel with a different handler if (this.get_requiresContainerScroll())

Page 47: Ajax Imp Codes

{ this.get_elementContainer().addEventListener( 'DOMMouseScroll', this._onContainerMouseWheel, false); }} // 3c) // Define the event handlers // _onContainerMouseWheel : function(e) { var _this = this._thisPrototype; // stop the mouse wheel from scrolling if (_this.get_mouseWheelScroll() == false) { e.preventDefault(); return false; }

// enforce mouse wheel scrolling else if (_this.get_mouseWheelScroll() == true) { var listBox = _this.get_element(); var container = this; var scrollingElement = this; var direction = (e.detail > 1) ? 1 : -1; // scroll the ListBox by the height of one item in the correct direction. var stepSize = scrollingElement.scrollHeight / listBox.options.length; var newScrollTop = scrollingElement.scrollTop + (stepSize * direction); scrollingElement.scrollTop = newScrollTop; // tell the browser we're taking care of the mouse wheel. e.preventDefault(); return false; } },

All of our target Firefox versions will now fully comply with the control's MouseWheelScroll setting when the cursor is positioned over the scrollbars. Congratulations, we can now check off requirement #2!

Home Stretch

Since that was so easy, let's do something a little more challenging. By default, Firefox 1.0 does not fire an onscroll event for either the ListBox or the DIV container when the mouse wheel is used to scroll. This means the hidden field isn't updated with the latest

Page 48: Ajax Imp Codes

positioning information. We can coax it into doing this, but first, let's examine the scenarios where it's necessary.

Remember, the default mouse wheel behavior for FF1 is to allow it to scroll the ListBox when horizontal scrolling is disabled and the ListBox has focus. This means that we'll have to register the _onMouseWheel handler even when MouseWheelScroll is NotSet (a.k.a. _mouseWheelScroll == null).

_initializeEvents : function() { // handle mouse wheel events separately from all others if (this.get_mouseWheelScroll() != null) { // ... } // MouseWheelScroll == NotSet, hack FF1 else if (!this.get_requiresContainerScroll() && this.get_scrollStateEnabled() && this.get_element().onmousewheel === undefined) { this.get_element().addEventListener( 'DOMMouseScroll', this._onMouseWheel, false); }

// ... },

Now, in the _onMouseWheel handler, we can try to handle the case where we need to update the scroll state in Firefox when horizontal scrolling is disabled, scroll state is enabled, and MouseWheelScroll is NotSet:

_onMouseWheel : function(e) { var _this = this._thisPrototype if (_this === undefined) _this = this; // stop the mouse wheel from scrolling if (_this.get_mouseWheelScroll() == false) { // ... } // enforce mouse wheel scrolling else if (_this.get_mouseWheelScroll() == true) { // ... } // MouseWheelScroll == NotSet, hack FF1 else if (!_this.get_requiresContainerScroll()

Page 49: Ajax Imp Codes

&& _this.get_scrollStateEnabled() && _this.get_element().onmousewheel === undefined) { _this._updateScrollState(); } },

I have to admit, it took me a little while to figure out why the above code wouldn't work. I kicked myself when I found out that this._thisPrototype was returning undefined. I forgot that in _initializeUI(), _thisPrototype is only defined when MouseWheelScroll is either Enforce or Prevent. We have to remove the conditional check in that function to so that we can have access to the DIV's _thisPrototype when MouseWheelScroll is NotSet. However, in the cases where this.get_elementContainer() returns null, we can't add a field to it.

_initializeUI : function() { var listBox = this.get_element(); var container = this.get_elementContainer(); // hack to support mouse wheel scrolling listBox._thisPrototype = this; if (container != null) { container._thisPrototype = this; } // ... },

Slide On In

The other case where we want to jimmy FF1 into doing the same thing is when MouseWheelScroll equals Enforce, but we have to do it in both the DIV's and in the ListBox's mouse wheel handlers. The hidden field must be updated near the end of the conditional block, just after the scrollTop property is set but before the return false line:

Collapse

_onContainerMouseWheel : function(e) { var _this = this._thisPrototype; // stop the mouse wheel from scrolling if (_this.get_mouseWheelScroll() == false) { // ... }

Page 50: Ajax Imp Codes

// enforce mouse wheel scrolling else if (_this.get_mouseWheelScroll() == true) { // ... scrollingElement.scrollTop = newScrollTop; // hack FF1 into saving scroll state if (_this.get_scrollStateEnabled()) { _this._updateScrollState(); }

// tell the browser we're taking care of the mouse wheel. e.preventDefault(); return false; } }, _onMouseWheel : function(e) { var _this = this._thisPrototype if (_this === undefined) _this = this; // stop the mouse wheel from scrolling if (_this.get_mouseWheelScroll() == false) { // ... } // enforce mouse wheel scrolling else if (_this.get_mouseWheelScroll() == true) { // ... scrollingElement.scrollTop = newScrollTop; // hack FF1 into saving scroll state if (this._thisPrototype != undefined && _this.get_scrollStateEnabled()) { _this._updateScrollState(); } // tell the browser we're taking care of the mouse wheel. e.preventDefault(); return false; } // MouseWheelScroll == NotSet, hack FF1 else if (!_this.get_requiresContainerScroll() && _this.get_scrollStateEnabled() && _this.get_element().onmousewheel === undefined) { // ... } }

Page 51: Ajax Imp Codes

,

...And for the first time in six articles, we can now say that our ListBox fully supports Firefox 1.0.

Introduction

As my first article on Code Project, I'd like to talk about a little proof of concept I created around AJAX/Atlas technologies. When I saw this screencast, I thought it could be easily used for a simple AJAX quiz system, so here I am :) The Code is really simple and there's no error management, but maybe later, I'll update this code to create a more complete solution.

Prerequisites

To be able to use this code, you'll have to do the following:

Install Atlas. Create an SQL database called AjaxQuiz and execute the SQL script which

comes with the source code.

Add a reference to the Atlas DLL (usually located in C:\Program Files\Microsoft ASP.NET\Atlas\v2.0.50727\Atlas).

Modify the AjaxQuiz connection string in web.config.

Page 52: Ajax Imp Codes

SQL code

The AjaxQuiz database contains three tables: t_Questions, t_Answers, and t_UserAnswers. There's also a single Stored Procedure called by our Web Method to process the data:

CREATE PROCEDURE dbo.ProcessNextQuestion ( @intQuestionID int = 0, @intAnswerID int = 0, @intUserID int = 0 )AS IF @intQuestionID > 0 AND @intAnswerID > 0 AND @intUserID > 0 BEGIN INSERT INTO t_UserAnswers(UserID, AnswerID, QuestionID) VALUES(@intUserID, @intAnswerID, @intQuestionID) END

SELECT TOP 1 QuestionID, QuestionText FROM t_Questions WHERE QuestionID > @intQuestionID

As you can see, if the SQL input parameter isn't null, the Stored Procedure inserts results of the previous question in the database. Then, it returns the text and ID for the next question. As the QuestionID is auto-incremented, the next question is always returned, but it supposes that IDs correspond to the desired question order.

Markup code

Markup code

There's only one web page in this small project: Default.aspx. First, I have to describe the ScriptManager element:

<atlas:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true"> <Scripts> <atlas:ScriptReference Path="AjaxQuiz.js" /> </Scripts> <Services> <atlas:ServiceReference Path="QuestionService.asmx" /> </Services></atlas:ScriptManager>

That's where Atlas is really nice: we just need to reference our JS client script and our Web Service, and Atlas will do the rest (the client code to consume the WS, etc.) In our JS code, we will also be able to create instances of classes defined in the server code. Atlas will do the correspondence for us.

Page 53: Ajax Imp Codes

<div id="StartForm"> <input id="btnStart" type="button" value="Start the Ajax Quiz !" onclick="Callback()" /></div><div id="QuizForm" style="display: none;"><div id="QuestionText"></div><br /> <input type="radio" id="YesAnswer" name="Answer" checked="checked" /> Yes <input type="radio" id="NoAnswer" name="Answer" /> No <input type="radio" id="DontKnowAnswer" name="Answer" /> ?<br /><br /> <input id="btnCallBack" type="button" value="Next" onclick="Callback()" /> <img id="imgUpdate" src="Images/spinner.gif" alt="Updating data" style="display: none;" /> <input id="QuestionID" type="hidden" value="0" /></div><div id="EndForm" style="display: none;">Thank you, this quiz is now finished ! </div>

Then, we add some HTML controls to create our form. First of all, there are three DIVs: one that shows on startup, another for quiz questions, and a last one displayed when the quiz is finished. The main section, QuizForm, contains three radio buttons for answers, a button to call our Web Service, and an image shown during AJAX calls.

Web Service

The Web Service contains only one WebMethod, StoreAnswer:

Collapse

/// <summary>/// That's the only Web Method used. It both stores the answer to the current question /// and sends data for the next one./// </summary>/// <param name="previousQuestion">A Question object containing user answer.</param>/// <returns>Returns a Question object containing data /// for the next question (question ID, question Text)</returns>[WebMethod]public Question StoreAnswer(Question previousQuestion){ // We initialize a Question object to null. It will be our return value. Question nextQuestion = null; if (previousQuestion == null) { // If no previous question is submitted, we create a new one with default values. previousQuestion = new Question(0, "", 0); }

Page 54: Ajax Imp Codes

// SQL connection initialization (connection string is in web.config file) using (SqlConnection cn = new SqlConnection( ConfigurationManager.ConnectionStrings["AjaxQuizConnectionString"].ConnectionString)) { try { // Then we call our stored procedure SqlCommand cmd = new SqlCommand("dbo.ProcessNextQuestion", cn); cmd.CommandType = CommandType.StoredProcedure; // First parameter for question ID. SqlParameter parm = new SqlParameter("@intQuestionID", SqlDbType.Int); parm.Value = previousQuestion.QuestionID; parm.Direction = ParameterDirection.Input; cmd.Parameters.Add(parm); // Second parameter for answer ID. SqlParameter parm2 = new SqlParameter("@intAnswerID", SqlDbType.Int); parm2.Value = previousQuestion.AnswerID; parm2.Direction = ParameterDirection.Input; cmd.Parameters.Add(parm2); // Third parameter for user ID. SqlParameter parm3 = new SqlParameter("@intUserID", SqlDbType.Int); parm3.Value = userID; parm3.Direction = ParameterDirection.Input; cmd.Parameters.Add(parm3); // Opening sql connection cn.Open(); using (SqlDataReader rd = cmd.ExecuteReader(CommandBehavior.CloseConnection)) { while (rd.Read()) { // We read data returned by our SP. It only returns one row. nextQuestion = new Question(rd.GetInt32(0), rd.GetString(1)); } } // We make the web service sleep for one second, // so that we can see the spinner image appear. // This line should be removed // if you seriously think about using this code ^^ Thread.Sleep(1000); } finally { // Important : we always have to close the sql connection cn.Close(); } } return nextQuestion;

Page 55: Ajax Imp Codes

}

The WebMethod calls a stored procedure, then returns the next question as a Question object. I made the thread sleep for one second, so that I can see the spinner image.

JavaScript code

The JavaScript code might be the hardest part, because we have to reference all our HTML objects and get/set their values. There must certainly be a simpler way to do the job, so don't hesitate to propose something in the comments section. The OnTimeout and OnError functions aren't included but are present in the Zip file.

Collapse

// Called on 'Next' button click event.function Callback(){ // Gets a reference to the hidden field containing the question ID

var questionID = document.getElementById('QuestionID'); // Gets references to the 3 possible answers

var answer1 = document.getElementById('YesAnswer'); var answer2 = document.getElementById('NoAnswer'); var answer3 = document.getElementById('DontKnowAnswer'); // Initializes a variable to hold the user answer

var answerID = 0; // Gets user answer

if(answer1.checked) answerID = 1; if(answer2.checked) answerID = 2; if(answer3.checked) answerID = 3; // Creates a new Question object. Atlas makes // the translation for us : JS and ASP.NET

// know exactly the same class !

var object = new Question(); object.QuestionID = questionID.value; object.AnswerID = answerID; // Displays a image during the AJAX call

DisplayUpdateImage(true); // Ajax call. QuestionService is the Web Service // we registered in Atlas ScriptManager // and as you can see, we can directly // call our WebMethod. Isn't it nice ? :) // We also add 3 events : one when process is completed, // another when a timeout occurs, // and a last one if an error occurs.

QuestionService.StoreAnswer(object, OnComplete, OnTimeout, OnError);}

Page 56: Ajax Imp Codes

// Called when Ajax request is donefunction OnComplete(response){ // 3 references to our 3 DIVs

var StartForm = document.getElementById('StartForm'); var QuizForm = document.getElementById('QuizForm'); var EndForm = document.getElementById('EndForm');

// A reference to the hidden field used to hold the question ID

var questionID = document.getElementById('QuestionID'); // A reference to the DIV which will contain the next question text

var questionText = document.getElementById('QuestionText');

// If there is a next question

if(response != null) { StartForm.style.display = 'none'; EndForm.style.display = 'none'; QuizForm.style.display = 'block'; questionID.value = response.QuestionID; questionText.innerHTML = response.QuestionText; } // If there's no more questions, we display the EndForm div. else { EndForm.style.display = 'block'; QuizForm.style.display = 'none'; } // We hide the updating image

DisplayUpdateImage(false);}

Conclusion

And that's all! When the user clicks on the Start button, he sees the first question appear. No result is inserted in the database, because the input Question object is null. Then, when he clicks on the Next button, results are stored in the database and our stored procedure sends the next question ... and so on until the Stored Procedure doesn't return anything. In that case, finally, the user sees the ending message.