Destination .NET! Platform Tools, Technologies & Resources
1 3 5 7 9
2 4 6 8 10
From VB4, C++ and Java to working on .Net Since Beta, 1.0.
Improving partner satisfaction and accelerating Microsoft platform adoption for managed ISVs.
Is your application compatible with Windows Vista? Make sure today by taking our self-test. Just follow the five steps of the Works with Windows Vista program so that you and your customers can be confident in your solution’s compatibility. Read More >>
What product/topic are you most interested in?
(Choose your top answer.)
Windows Vista
Windows Server 2008
2007 Microsoft Office system
SQL Server 2008
ASP.NET
Visual Studio 2008
Windows Mobile
Software as a Service
A little bit of everything
Just browsing, thanks

View Results
Whether you love the site or hate it, we want to know. Tell us what topics to cover, help us improve things, or just sound off on something we could've done better. Send your feedback directly to the editor by email.
 Print Print
Average Rating: 5/5 | Rate this item | 1 user has rated this item.
Building the DevX Destination.NET Windows® Sidebar Gadget (cont'd)

JavaScript Walkthrough #1: Gadget

Note: the following two sections do a basic walkthrough of JavaScript code from two files. This code is annotated much more extensively in the source files available with the gadget download.

As one might imagine, things got more complicated when it came to the JavaScript. The primary JavaScript file, dnetgadget.js, has two primary purposes:

  1. Use some Ajax functionality to read the RSS feed and populate the headline elements
  2. Handle navigation events

In addition, the initial function needs to do some Gadget-related housekeeping, such as hooking up the flyout and settings pages. For example, in setup() I have:

 System.Gadget.Flyout.file = 'flyout.html'; 

This tells the Gadget to use its built-in flyout functionality, with very cool Gadget shrinkage, on my flyout.html file. Similarly,

 System.Gadget.settingsUI = 'settings.html'; 
sets the built-in Settings dialogue to display my settings.html file. One more line specifies the event handler to trigger when the user closes the Settings panel. More on that in a moment.
 System.Gadget.onSettingsClosed = settingsClosed; 

Because the feature spec for this particular Gadget includes category and subject filtering, as well, this code required some additional functionality to process choices made on the Settings page. As a result, the code checks for existing values for both "category" and "subject". Note that the System.Gadget class provides a static Settings object for storage of Gadget-wide variables, which also assists in maintaining state between the various Gadget pages and instantiations of the Gadget. Undeclared variables default to empty strings rather than nulls, so in my setup() function, I also do a quick check:

 if (System.Gadget.Settings.read('category') == '')
	{
		System.Gadget.Settings.write('category','All');
	}

	if (System.Gadget.Settings.read('subject') == '')
	{
		System.Gadget.Settings.write('subject','All');
	}

Once the setup finishes, routine Ajax code starts up the http object, pulling headlines from an RSS syndication url provided by DevX:

 try {
	  titles = new ActiveXObject('Msxml2.XMLHTTP');
  url = 'http://services.devx.com/outgoing/destinationNetCategorized.xml';
  titles.open('GET', url, true);
  titles.onreadystatechange = catchRSSFeed;
  titles.send(null);
	} catch (err) {
  headline.innerHTML = 'Could not open RSS feed. (Error: ' + err.Description + ')';
  titles = null;
	}

For handling the category and subject settings, I decided to go with client-side filtering, which offered the performance benefit of doing a single http call, rather than server-side filtering, which would require new calls every time new filtering options were chosen. To handle this kind of filtering, I chose to create an array of indices that referenced members of the http object holding the headlines. This alleviated the overhead of duplicating heavy and redundant http objects or multi-dimensional arrays.

 function filterHeadlines() {
	headline.innerHTML = 'Filtering headlines...';

	System.Gadget.Flyout.show = false;
	filtered = new Array();
	thisFItem = -1;
	var currCat = System.Gadget.Settings.read('category');
	var currSub = System.Gadget.Settings.read('subject');
	for (var filtNum=0; filtNum<items.length; filtNum++)
	{
	  if (((currCat == 'All') ||
	   (items[filtNum].selectSingleNode('categories').text.indexOf(currCat,0) >= 0)) &&
	   ((currSub == 'All') ||
	   (items[filtNum].selectSingleNode('categories').text.indexOf(currSub,0) >= 0)))
	  {

	   thisFItem++;
	   filtered[thisFItem] = filtNum;
	  }
	}
	if (thisFItem == -1)
	{
	   headline.innerHTML = 'No headlines available based on the selected filters.';
	   navplace.innerHTML = '0 of 0';
	}

	// Otherwise, reset to the first available headline and display it.
	else
	{
	   thisFItem = 0;
	   thisItem = filtered[thisFItem];
	   updateHeadline();
	}
}

When flipping through headlines, I decided to keep things simple. Because of the filtering technique, navigation would actually affect the filtered list, and then populate page elements based on the original content object.

 function next() {
	if ((filtered != null) && (filtered.length > 0))
	{
		if (thisFItem < filtered.length-1)
		{
			thisFItem++;
		}
		else
		{
			thisFItem = 0;
		}
		thisItem = filtered[thisFItem];
		updateHeadline();
	}
}

function prev() {
	if ((filtered != null) && (filtered.length > 0))
	{
		if (thisFItem > 0)
		{
			thisFItem--;
		}
		else
		{
			thisFItem = filtered.length-1;
		}
		thisItem = filtered[thisFItem];
		updateHeadline();
	}
}

Updating the headline thus becomes a simple affair:

 function updateHeadline() {
	System.Gadget.Flyout.show = false;
	headline.innerHTML = items[thisItem].firstChild.text;
	navplace.innerHTML = (thisFItem + 1) + ' of ' + filtered.length;
}

Because I chose to combine flyout and main functionality in the same JavaScript source, this code includes the flyout bits. This type of flyout is really simple. When the user clicks the headline, the flyout() function writes relevant data to the Settings object, then shows the flyout. Since flyout.html catches the onload event of the body, this triggers the next function, buildFlyout(), which sets the flyout dimensions and reads those Settings variables into the page elements. Download the Gadget and take a look inside to see what I mean.

Remember how the setup() function assigns an event handler to System.Gadget.onSettingsClosed? I finish the file with that handler, which demonstrates how to catch the Ok and Cancel click action on the pre-built Settings panel. Note that this is part two of a sequence that kicks off in the JavaScript for the Settings page, which is described next.

 function settingsClosed(event)
{
    if(event.closeAction == event.Action.commit)
    {
		filterHeadlines();
    }
    else if (event.closeAction == event.Action.cancel)
    {
    }
}

Page 5 of 7
Previous Page: Special Considerations for CSS Next Page: JavaScript Walkthrough #2: Setting
Page 1: Architectural OverviewPage 5: JavaScript Walkthrough #1: Gadget
Page 2: Architectural Overview continuedPage 6: JavaScript Walkthrough #2: Setting
Page 3: Architecting the RSS ReaderPage 7: Deployment, Wrap-up, Lessons Learned
Page 4: Special Considerations for CSS 
Submit article to:
Extending your solution to run on Microsoft technology is easier than ever. Through NXT, you can reach more customers, increase revenues and slash development time and costs, accelerating both your time to market and profitability. Get the details on NTX. >>
Sign up for your free e-mail newsletters today!
DevX Windows Developer Update

More Newsletters
.NET Building Blocks: Custom User Control Fundamentals
Quickly Copy Data Rows from DataReader to a DataTable
Introduction to the WPF Command Framework
Taming Trees: Building Branching Structures
Implement Drag and Drop in Your Windows Forms Applications



JupiterOnlineMedia

internet.com earthweb.com Devx.com mediabistro.com Graphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info

Copyright 2008 Jupitermedia Corporation All Rights Reserved.
Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Web Hosting | Newsletters | Tech Jobs | Shopping | E-mail Offers