Creating Blocks on Poplfy.com

me This article is going to be more or less a tutorial on how to create a block in Popfly. This block will dynamically stream XML data from an external site and then render it. Having said that, what are we setting out to create? Well, our end goal in this tutorial will be to create a gadget for World of WarCraft players which they’ll be able to put up on their site, and show off their character’s information with regard to the items they are carrying and other bit and bobs. So, in order to display all of this character data we'll need some sort of data feed. Luckily for us, http://www.wowarmory.com/ and the EU site http://eu.wowarmory.com/ does this all for us. However, to make thing slightly more complex there are feed issues and other fun problems when requesting information directly from the armoury. The other reason I am not connecting directly is to store statistics of all of the signatures requested so that I can see its popularity etc.
Hugh Site

Difficulty: Intermediate
Time Required: 6-10 hours
Cost: Free
Software: Notepad, Popfly (popfly.com), Firefox with Firebug extension
Hardware: None

Popfly is a really easy to use web application which allows developers to create mini or complex web apps and share them within the Popfly community. On the other hand, new users can take these “blocks” which have been developed and “mash” them together to create even more complex applications like an image gallery for Facebook. This really creates quite a wide array of possibilities that can be explored with the application. Not only this but users can create their own websites with their “mash-ups” or implement them on their existing site.

Popfly primarily uses JavaScript as its programming platform. Not only this, but Popfly has a variety of AJAX libraries and other cool script libraries to create more interesting applications which can also be used with Silverlight.

Breaking down the Armoury XML

So now that we have the basics out of the way, we can start to decode the 120 lines of XML we have to go through, as you can appreciate this is no easy task. For programming purposes I will be using my brother’s World of WarCraft Character Data:

Server : EU
Realm : Moongalde
Character Name : Raymar

I will use this data to query the WOW servers for my character data.

http://wow.ukgl.co.uk/wow_xml.cfm?s=EU&r=Moonglade&n=Raymar

And for those of you who are interested, the CFML code is (this is a very basic version, does not include character parsing etc and stats):

 1: <cfparam name="xml_feed" default="">
 2: <cfprocessingdirective suppresswhitespace="yes">
 3: <cfcontent type="text/xml" reset="yes">
 4: <cfset strUserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3" />
 5: <cfif xml_feed eq "">
 6: <cfif #URL.s# eq "EU">
 7: <cfhttp url="http://eu.wowarmory.com/character-sheet.xml?r=#URL.r#&n=#URL.n#" method="GET" useragent="#strUserAgent#" />
 8: </cfif>
 9: <cfif #URL.s# eq "US">
 10: <cfhttp url="http://wowarmory.com/character-sheet.xml?r=#URL.r#&n=#URL.n#" method="GET" useragent="#strUserAgent#" />
 11: </cfif>
 12: <cfoutput>#cfhttp.FileContent#</cfoutput>
 13: </cfif>
 14: <cfif xml_feed eq "items">
 15: <cfif #URL.s# eq "EU">
 16: <cfhttp url="http://eu.wowarmory.com/item-info.xml?i=#URL.i#" method="GET" useragent="#strUserAgent#" />
 17: </cfif>
 18: <cfif #URL.s# eq "US">
 19: <cfhttp url="http://wowarmory.com/item-info.xml?i=#URL.i#" method="GET" useragent="#strUserAgent#" />
 20: </cfif>
 21: <cfoutput>#cfhttp.FileContent#</cfoutput>
 22: </cfif>
 23: <cfif xml_feed eq "item_detail">
 24: <cfif #URL.s# eq "EU">
 25: <cfhttp url="http://eu.wowarmory.com/item-tooltip.xml?i=#URL.i#" method="GET" useragent="#strUserAgent#" />
 26: </cfif>
 27: <cfif #URL.s# eq "US">
 28: <cfhttp url="http://wowarmory.com/item-tooltip.xml?i=#URL.i#" method="GET" useragent="#strUserAgent#" />
 29: </cfif>
 30: <cfoutput>#cfhttp.FileContent#</cfoutput>
 31: </cfif>
 32: </cfcontent>
 33: </cfprocessingdirective>

Note, ColdFusion will need to be running on the server.

Once this is done, the following XML data will be returned, as there is a lot of data I am going to break it down step by step. The first thing you'll notice is the entire XML sheet is wrapped with the tags:

<page globalSearch="1" lang="en_gb" requestUrl="/character-sheet.xml">
<characterInfo>

Right, now the information we really care about comes after this. The first of which is the actual character information.

<character battleGroup="Reckoning" charUrl="r=Moonglade&n=Raymar" class="Warrior" classId="1" faction="Horde" factionId="1" gender="Male" genderId="0" guildName="Temper" guildUrl="r=Moonglade&n=Temper&p=1" lastModified="30 August 2007" level="70" name="Raymar" race="Tauren" raceId="6" realm="Moonglade" title="">

This supplies us with all of the basic information surrounding my character. As you'll also notice, all of the values are XML attributes. One of the more important aspects of this is the classId (classId="1"), for this we will actually need to know what

Class ID Class Name Talent 1 Talent 3 Talent 2 Bar 2 Name Bar 2 Colour
1 Warrior Arms Fury Protection RAGE RED
2 Paladin Holy Protection Retribution MANA BLUE
3 Hunter Beast Mastery Marksmanship Survival MANA BLUE
4 Rogue Assassination Combat Subtlety ENERGY YELLOW
5 Priest Discipline Holy Shadow MANA BLUE
7 Shaman Elemental Enhancement Restoration MANA BLUE
8 Mage Arcane Fire Frost MANA BLUE
9 Warlock Affliction Demonology Destruction MANA BLUE
11 Druid Balance Feral Restoration MANA BLUE

Now that we know how the characters are structured in World Of WarCraft we can use this information to help start to create an initial start point for the document. But before we start, there is still a lot more of the XML we must first understand.

As you can see from above, I have listed the talents for each character. These talents have also been listed in a specific order. The next crucial segment of XML we need to understand rests with the “<characterTab>” tags. The first node we get to is the Talent Spec. This node contains three attributes which consequently refer to the character’s class. So our character Raymar has the classId 1. So, looking at our table, Raymar’s talents are: Arms, Fury and Protection. If we now refer back to the XML:

<talentSpec treeOne="41" treeThree="0" treeTwo="20"/>

Let’s break this down. Each of these attributes; treeOne, treeThree and treeTwo need to be assigned to the correct Talent Name which in this case is:

Arms = 41 (treeOne)
Fury = 0 (treeThree)
Protection = 20 (treeTwo)

The above classes in the table are broken down correctly.

The rest of the XML is the same, we will be calling values, but this will not have any reference to a set variable like the talents above.

The next important part of this XML breakdown to note is, the characters items list. In order for us to give a more comprehensive and in-depth looks at a character’s items, the character XML provides us with the following information:

<item durability="59" gem0Id="0" gem1Id="0" gem2Id="0" icon="inv_helmet_25" id="28180" maxDurability="80" permanentenchant="0" randomPropertiesId="0" seed="370856290" slot="0"/>

The only real information we need is the; icon, id and the slot, the rest we can take from another XML feed. This next XML feed we get from the CFML URL address:

http://wow.ukgl.co.uk/wow_xml.cfm?xml_feed=item_detail&s=EU &i=28180

This will go and get the XML for the item “28180”. At the moment, the actual name for the item is unknown so this new XML feed has to be loaded before the name can be displayed.

 1: <?xml version="1.0" encoding="UTF-8"?>
 2: <?xml-stylesheet type="text/xsl" href="/layout/item-tooltip.xsl"?>
 3: <page globalSearch="1" lang="en_gb" requestUrl="/item-tooltip.xml">
 4: <itemTooltips>
 5: <itemTooltip>
 6: <id>28180</id>
 7: <name>Myrmidon's Headdress</name>
 8: <icon>inv_helmet_25</icon>
 9: <overallQualityId>3</overallQualityId>
 10: <bonding>1</bonding>
 11: <classId>4</classId>
 12: <equipData>
 13: <inventoryType>1</inventoryType>
 14: subclassName>Plate</subclassName>
 15: </equipData>
 16: <damageData/>
 17: <bonusStrength>17</bonusStrength>
 18: bonusStamina>37</bonusStamina>
 19: <armor armorBonus="0">946</armor>
 20: <socketData>
 21: <socket color="Red"/>
 22: <socket color="Meta"/>
 23: <socketMatchEnchant>+4 Strength</socketMatchEnchant>
 24: </socketData>
 25: <durability current="80" max="80"/>
 26: <bonusDefenseSkillRating>33</bonusDefenseSkillRating>
 27: <itemSource reqLvl="67" value="sourceType.questReward"/>
 28: </itemTooltip>
 29: </itemTooltips>
 30: </page>

The program

So now that we understand how XML works and how the actual XML is laid out from the WOW servers we can begin to write our program. For this, we are going to use Popfly. You’ll need to register or be part of the alpha to continue.

To start, let’s create a fresh block. To do this on the “Create Stuff” drop down menu select “Block”.

When the page loads the first thing you notice is the big text area - this is your space.

clip_image002

There are two tabs. The first one uses XML to generate a profile about your block and the other allows you to program your block. Let’s start off by creating the basis for our application by defining the project title and other parameters.

Be sure to save your work as you go along!

As we are using XML to define the project, we must remember that we’ll have to close all of the tags we open.

We now need to understand the XML tags popfly uses to understand what the application is and what it will do. To do this simply, I have created the following table.

XML Tag

Description

<block>

This tag also uses the following attributes:

·         Class

·         hasInitialize

·         type

<providerName>

This is your name or companies name who has written the block.

<providerUrl>

This is a link to your website.

<providerLogoUrl>

This is your larger logo URL

<blockIconUrl>

This is the icon URL for your block this must be 16x16.

<description>

Allows for a description to be used, this maybe the description for the block or the operators or text boxes.

<operations>

This tells popfly that you are defining your blocks functions.

<operation>

name

<inputs>

Tells the popfly application that you are about to define your input boxes.

<input>

Name, required

<defaultValue>

You can specify a default value for your text box.

<constraints>

You can specify and constraints this is mainly used for validation to check for number or an email address. We won’t need to use this.

This is a very brief overview of the Tags that are available to us. As you can see below, this is what I have written to setup my block. For this tutorial please ensure that you DO NOT modify the XML highlighted unless of course you know what you are doing.

 1: <?xml version="1.0"?>
 2: <block class="ukgl_wow" hasInitialize="true" type="display">
 3: <providerName>World Of Warcraft Signature Generator</providerName>
 4: <providerUrl>http://wow.ukgl.co.uk</providerUrl>
 5: <providerLogoUrl></providerLogoUrl>
 6: <blockIconUrl>/content/components/icons/block.png</blockIconUrl>
 7: <description>UKGL Silverlight World Of WarCraft Signature generator.</description>
 8: <operations>
 9: <operation name="GetCharacter">
 10: <description>Add a character.</description>
 11: <inputs>
 12: <input name="server" required="true">
 13: <description>Server EU/US</description>
 14: <defaultValue>EU</defaultValue>
 15: <constraints/>
 16: </input>
 17: <input name="realm" required="true">
 18: <description>Realm</description>
 19: <defaultValue>Moonglade</defaultValue>
 20: <constraints/>
 21: </input>
 22: <input name="character" required="true">
 23: <description>Character Name</description>
 24: <defaultValue>Raymar</defaultValue>
 25: <constraints/>
 26: </input>
 27: <input name="bg_url" required="true">
 28: <description>Please ensure that the background is either a gif, jpg or png and is 450 px by 80 px!</description>
 29: <defaultValue>none</defaultValue>
 30: <constraints/>
 31: </input>
 32: <input name="avatar" required="true">
 33: <description>Please ensure that the character image is either a gif, jpg or png and is 64 px by 64 px</description>
 34: <defaultValue>none</defaultValue>
 35: <constraints/>
 36: </input>
 37: </inputs>
 38: </operation>
 39: </operations>
 40: <objects/>
 41: </block>

The JavaScript

Popfly works by using and calling function like any other JavaScript based program. To start, we’ll need to initialize the project. To do this we’ll use the following function.

function ukgl_wow () {
};

     Next we’ll create a function to actually run the application. Looking back at our original XML we used the XML operation tag to define the block function. We’ll now need to call in this function using the JavaScript. We will also need to get the data that will be entered into the forms.

ukgl_wow.prototype.GetCharacter = function(server, realm, character, bg_url, avatar) {
};

This will not go and get the data from the five input fields we created back in the XML document. To make things easier we are now going to define these new variables; server, realm character, bg_url and avatar as variables.

var getServer = server;
var getRealm = realm;
var getCharacter = character;
var getBgURL = bg_url;
var getAvatar = avatar;

  You don’t have to do this but it makes things easier. The next thing we’ll need to do is test the data being submitted to the application. The easiest test to do is to just check to see if values are actually present.

 1: if (getServer == "") {
 2: alert("Please enter a server, 'EU' or 'US'");
 3: }
 4: if (getRealm == "") {
 5: alert("Please enter a realm");
 6: }
 7: if (getCharacter == "") {
 8: alert("Please enter a character name");
 9: }
 10: if(getBgURL == "none") {
 11: var setBgURL = "http://wow.ukgl.co.uk/img/backgrounds/default/default.gif";
 12: } else {
 13: var setBgURL = getBgURL;
 14: }

So this segment of code is just simply checking our set variables to make sure that they are not blank and if they are then alerting the user to the problem.

Not only this but, we are also checking to see if a URL for a background has been defined and hasn’t been left as “none”. If an image has in fact not been defined then a default is set or else the users entered background is used.

Right, now that’s out of the way, we will need to start breaking down the XML data, but first we will need to connect to our data source.

 1: document.body.style.backgroundColor='transparent';
 2:  
 3: try {
 4: var base_xml = environment.getXml("http://wow.ukgl.co.uk/wow_xml.cfm?s="+getServer+"&r="+getRealm+"&n="+getCharacter);
 5: } catch (err) {
 6: txt="A connection to the WOW servers has failed.\n\n"
 7: txt+="Error description: " + err.description + "\n\n"
 8: txt+="Click OK to continue.\n\n"
 9: alert(txt);
 10: }

So, the first thing we are doing with this segment of code is actually telling silver light that we want a transparent background.

Next, we are going to use the “try” function. This will basically try to get the XML feed and if it fails it will throw back an error. So, in order to connect to an XML data source, we will need to use the “environment.getXML()” function. Alongside this, we are going to define it as a variable as well so that we can easily query it instead of using repeatedly.

In this instance, I am using my server from the XML feed.

http://wow.ukgl.co.uk/wow_xml.cfm?s="+getServer+"&r="+getRealm+"&n="+getCharacter

And within this, we need to include our variables that handle the form data so that users can enter in their own data.

Lastly, if there is an error we can use the “catch” function to catch the error if there is one. If there is, then the “alert” function is used again to display a pop-up to the user, alerting them to the fact that an error has occurred whilst connecting to the server.

Right, this is where is gets complicated as we start to drill right down into the XML.

 1: // <page><characterInfo><character>
 2: var character = base_xml.selectSingleNode("/page/characterInfo/character");
 3: // <page><characterInfo><characterTab><characterBars>
 4: var characterBars = base_xml.selectSingleNode("/page/characterInfo/characterTab/characterBars");
 5: // <page><characterInfo><characterTab><items>
 6: var items = base_xml.selectNodes("/page/characterInfo/characterTab/items/item");
 7: // <page><characterInfo><characterTab><pvp>
 8: var pvp = base_xml.selectSingleNode("/page/characterInfo/characterTab/pvp/lifetimehonorablekills");
 9: // <page><characterInfo><characterTab><knownTitles>
 10: var knownTitles = base_xml.selectSingleNode("/page/characterInfo/characterTab/knownTitles/title");
 11: // <page><characterInfo><characterTab><talentSpec>
 12: var talentSpec = base_xml.selectSingleNode("/page/characterInfo/characterTab/talentSpec");

For cross browser compatibility I have used the following function

selectSingleNode

For ease of use I have commented just above the variable with its relevant XML path/node.

Again, this code segment is for easy use throughout the rest of the program so that if Blizzard makes changes to their XML structure then changes can be made quickly. It also helps keep the code tidy.

if(character.getAttribute("name") == "") {
alert("The information you have supplied, server, realm or name is incorrect as you characters information could not be loaded.");
}

Again, this just loads the XML of the character variable and checks to see if the “name” attribute exists (Highlighted in red). This basically checks to see if a valid character has been loaded.

<character battleGroup="Reckoning" charUrl="r=Moonglade&n=Raymar" class="Warrior" classId="1" faction="Horde" factionId="1" gender="Male" genderId="0" guildName="Temper" guildUrl="r=Moonglade&n=Temper&p=1" lastModified="30 August 2007" level="70" name="Raymar" race="Tauren" raceId="6" realm="Moonglade" title="">

Right, this may look a little daunting and complex but this is the navigation that will run along the bottom. The “\” is used to remove the ‘ from parsing or else it would be counted and the variable would stop working.

The navigation is going to be broken down into 6 tabs, these are:

· Home
This tab will contain the users character class, character name, a guild name if they have one, the server and realm they play on, their characters health and secondary bar (MANA, ENERGY, RAGE) and finally the date of when they were last online.

· Armour
This tab will list all of the users items.

· Weapons
This tab will list all of the users weapons.

· PVP
This tabs will show the players PVP information, which will include their rank and their total amount of kills.

· Stats
Stats will list all of the players statistics including their; base stats, Melee, Defence, Resistances, Spell and Range.

· Talents
This last tab will show the characters talent stats, each classes talents has been highlighted in the table above.

 1: var navigation = '<td colspan="3" style="padding-right: 7px;" align="right" valign="top"><a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'show\',\'m_armour\',\'\',\'hide\',\'m_weapons\',\'\',\'hide\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'hide\',\'m_talents\',\'\',\'hide\',\'m_viewitem\',\'\',\'hide\')"><img src="http://video.ch9.ms/ecn/c4fcontent/migration/5848815/home_off.gif" border="0" /></a> 

      
 2: <a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'hide\',\'m_armour\',\'\',\'show\',\'m_weapons\',\'\',\'hide\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'hide\',\'m_talents\',\'\',\'hide\',\'m_viewitem\',\'\',\'hide\')"><img src="http://video.ch9.ms/ecn/c4fcontent/migration/5848815/armour_off.gif" border="0" /></a>
 3: <a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'hide\',\'m_armour\',\'\',\'hide\',\'m_weapons\',\'\',\'show\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'hide\',\'m_talents\',\'\',\'hide\',\'m_viewitem\',\'\',\'hide\')"><img src="http://video.ch9.ms/ecn/c4fcontent/migration/5848815/weapons_off.gif" border="0" /><a/>
 4: <a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'hide\',\'m_armour\',\'\',\'hide\',\'m_weapons\',\'\',\'hide\',\'m_pvp\',\'\',\'show\',\'m_stats\',\'\',\'hide\',\'m_talents\',\'\',\'hide\',\'m_viewitem\',\'\',\'hide\')"><img src="http://video.ch9.ms/ecn/c4fcontent/migration/5848815/pvp_off.gif" border="0" /></a>
 5: <a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'hide\',\'m_armour\',\'\',\'hide\',\'m_weapons\',\'\',\'hide\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'show\',\'m_talents\',\'\',\'hide\',\'m_viewitem\',\'\',\'hide\')"><img src="http://video.ch9.ms/ecn/c4fcontent/migration/5848815/stats_off.gif" border="0" /></a>
 6: <a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'hide\',\'m_armour\',\'\',\'hide\',\'m_weapons\',\'\',\'hide\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'hide\',\'m_talents\',\'\',\'show\',\'m_viewitem\',\'\',\'hide\')"><img src="http://video.ch9.ms/ecn/c4fcontent/migration/5848815/talents_off.gif" border="0" /></a></td>'
;

I have pre-included an “onclick()” function which I’ll explain in more detail later but essentially it’s going to create our navigation system.

Now, I like to use JavaScript variables instead of CSS, I really don’t know why but there we go. So here, I have a list of the fonts and styles I will be using for my project.

 1: //FONTS
 2: var stxt10 = '<font style="font-family:Verdana, Arial, Helvetica, sans-serif; color:#000000; font-size:10px;">';
 3:  
 4: var stxt10bw = '<font style="font-family:Verdana, Arial, Helvetica, sans-serif; color:#ffffff; font-size:10px; font-weight:bold;">';
 5:  
 6: var stxt10b = '<font style="font-family:Verdana, Arial, Helvetica, sans-serif; color:#000000; font-size:10px; font-weight:bold;">';
 7:  
 8: var stxt12b = '<font style="font-family:Verdana, Arial, Helvetica, sans-serif; color:#000000; font-size:12px; font-weight:bold;">';
 9:  
 10: var stxt12 = '<font style="font-family:Verdana, Arial, Helvetica, sans-serif; color:#000000; font-size:12px;">';
 11:  
 12: var stxt16b = '<font style="font-family:Verdana, Arial, Helvetica, sans-serif; color:#000000; font-size:16px; font-weight:bold;">';
 13:  
 14: var txt9 = 'font-family:Verdana, Arial, Helvetica, sans-serif; color:#000000; font-size:9px;';
 15:  
 16: var txt12 = 'font-family:Verdana, Arial, Helvetica, sans-serif; font-size:12px;';
 17:  
 18: var txt12_b = 'font-family:Verdana, Arial, Helvetica, sans-serif; color:#000000; font-size:12px;';
 19:  
 20: var fl = 'float:left; position:absolute; width:450px; height:80px; background-color:#CCCCCC; z-index:1; vertical-align:middle; background:#000000 url('+setBgURL+') no-repeat center; background-position:top;';
 21:  
 22: var m_viewitem = 'float:right; position:absolute; width:376px; height:45px; margin-left: 74px; margin-bottom: 30px; padding-left: 0px; padding-top: 7px; z-index:1; background:#000000 url('+setBgURL+') no-repeat center; background-position:top right;';
 23:  
 24: var m_stats_detail = 'float:right; position:absolute; width:376px; height:45px; margin-left: 74px; margin-bottom: 30px; padding-left: 0px; padding-top: 7px; z-index:1; background:#000000 url('+setBgURL+') no-repeat center; background-position:top right;';
 25:  
 26: var div_item_holder = '<div style="float:left; height:21; width:21; padding-bottom: 0px; padding-left: 0px; padding-right: 1px; padding-top: 0px;">';
 27:  
 28: var items_padding = '<div style="height:47; vertical-align:bottom; padding-bottom: 5px; text-align:left;"></div>';
 29:  
 30: var font_close = '</font>';

Right, for our signature we are going to include a user avatar. At the beginning, we specified a field for a custom avatar to be entered by the user. If they don’t specify one however, we’ll need to connect up to the WOW servers again to retrieve a static one.

So to do this, we will call a simple if statement to check to see if anything hasn’t been entered.

if(getAvatar == "none") {

So now that we know that the user has not entered a custom URL, we need to check to see if they have a level 70 character and if so, we need to specify the correct directory to fetch the image out of.

So here, if the user has a character that is equal to level 70 then the variable “dirId” is set as “wow-70” or if their character is below level 70 then the “dirId” is set as “wow”.

if (character.attributes.level == 70) {
var dirId = 'wow-70';
} else {
var dirId = 'wow';
};

Next, we are going to create another variable which will hold our users avatar. Right, we know that we can fetch character avatars from:

http://armory.worldofwarcraft.com/images/portraits/

Then we’ll need:

/dirId/

Which will either be “wow-70” or “wow” depending on whether or not the users character is level 70 or not and then lastly, on top of this, to get the characters portrait broken up into three variables.

· Gender

· Race

· Class

So you end up with:

http://video.ch9.ms/ecn/c4fcontent/migration/5848815/0-0-0.gif

 1: var dlft_set_img = '';
 2: dlft_set_img += '<img src="http://armory.worldofwarcraft.com/images/portraits/';
 3: dlft_set_img += dirId;
 4: dlft_set_img += '/';
 5: dlft_set_img += character.getAttribute("genderId");
 6: dlft_set_img += '-';
 7: dlft_set_img += character.getAttribute("raceId");
 8: dlft_set_img += '-';
 9: dlft_set_img += character.getAttribute("classId");
 10: dlft_set_img += '.gif" hieght="64" width="64" />';
 11: var set_img = dlft_set_img;
 12: var usr_picture = '';
 13: usr_picture += '<div id="picture" style="height:64; width:64; padding-bottom: 1px; padding-left: 9px; padding-right: 8px; padding-top: 8px;">';
 14: usr_picture += set_img;
 15: usr_picture += '</div>';

Lastly, we’ll need to accommodate for customised avatars. This is more or less the same thing apart from it goes and pulls the entered value from the avatar field.

 1: } else {
 2: var set_img = getAvatar;
 3: var usr_picture = '';
 4: usr_picture += '<div id="picture" style="height:64; width:64; padding-bottom: 1px; padding-left: 9px; padding-right: 8px; padding-top: 8px;">';
 5: usr_picture += '<img src="';
 6: usr_picture += set_img;
 7: usr_picture += '" hieght="64" width="64" />';
 8: usr_picture += '</div>';
 9: }

As I showed you earlier in the class break down table, we will need to assign some variables that aren’t in the XML to each class.

So as you can see in the code below, I have broken down each class and used an ‘if’ statement to check the “classId“ and then I have assigned my own static variables which we will come back to later, both in the home and talents tab.

 1: // CLASSES
 2: var char_class = "na";
 3: var bar2name = "na";
 4: var bar2colour = "na";
 5: //Warrior
 6: if (character.getAttribute("classId") == "1") {
 7: var char_class = "Warrior";
 8: var talent1 = "Arms";
 9: var talent2 = "Fury";
 10: var talent3 = "Protection";
 11: var bar2name = "RAGE";
 12: var bar2colour = "red";
 13: };
 14: //paladin 
 15: if (character.getAttribute("classId") == "2") {
 16: var char_class = "Paladin";
 17: var talent1 = "Holy";
 18: var talent2 = "Protection";
 19: var talent3 = "Retribution";
 20: var bar2name = "MANA";
 21: var bar2colour = "blue";
 22: };
 23: //hunter 
 24: if (character.getAttribute("classId") == "3") {
 25: var char_class = "Hunter";
 26: var talent1 = "Beast Mastery";
 27: var talent2 = "Marksmanship";
 28: var talent3 = "Survival";
 29: var bar2name = "MANA";
 30: var bar2colour = "blue";
 31: };
 32: //Rogue 
 33: if (character.getAttribute("classId") == "4") {
 34: var char_class = "Rogue";
 35: var talent1 = "Assassination";
 36: var talent2 = "Combat";
 37: var talent3 = "Subtlety";
 38: var bar2name = "ENERGY";
 39: var bar2colour = "yellow";
 40: };
 41: //priest 
 42: if (character.getAttribute("classId") == "5") {
 43: var char_class = "Priest";
 44: var talent1 = "Discipline";
 45: var talent2 = "Holy";
 46: var talent3 = "Shadow";
 47: var bar2name = "MANA";
 48: var bar2colour = "blue";
 49: };
 50: //shaman
 51: if (character.getAttribute("classId")== "7") {
 52: var char_class = "Shaman";
 53: var talent1 = "Elemental";
 54: var talent2 = "Enhancement";
 55: var talent3 = "Restoration";
 56: var bar2name = "MANA";
 57: var bar2colour = "blue";
 58: };
 59: //mage
 60: if (character.getAttribute("classId") == "8") {
 61: var char_class = "Mage";
 62: var talent1 = "Arcane";
 63: var talent2 = "Fire";
 64: var talent3 = "Frost";
 65: var bar2name = "MANA";
 66: var bar2colour = "blue";
 67: };
 68: //warlock 
 69: if (character.getAttribute("classId") == "9") {
 70: var char_class = "Warlock";
 71: var talent1 = "Affliction";
 72: var talent2 = "Demonology";
 73: var talent3 = "Destruction";
 74: var bar2name = "MANA";
 75: var bar2colour = "blue";
 76: };
 77: //druid
 78: if (character.getAttribute("classId")== "11") {
 79: var char_class = "Druid";
 80: var talent1 = "Balance";
 81: var talent2 = "Feral";
 82: var talent3 = "Restoration";
 83: var bar2name = "MANA";
 84: var bar2colour = "blue";
 85: };

Right we have now assigned each class its talents class name and what their second bar shows. Now we get on to the exciting stuff. We are now going to get the application to automatically generate all of the items and weapons for our character. To do this, we are going to keep things really simple with a loop function. Right let’s start of by setting up some quick variables.

var weapons_list = ''
var item_list = '';

var get_items = items;

Right, get_items is calling all of the XML nodes for the items. As there is a list, we will need to create a loop in order to individually select each row and then output an appropriate icon and link.

So to begin with, we are going to start a row 0 (var i = 0). Then we are going to count up all of the rows of items (get_items.length) and if there are more rows (i<) we will continue the loop.

Next, we are going to set the variable curr_item which then allows us to individually select each row (get_items[i]).

for (var i = 0; i<get_items.length; i++) {

var curr_item = get_items[i];

Now, the World of WarCraft XML data sheet includes both weapons and armour but each item also shares its own unique slot. So, for example each character can only bare 3 weapons. We know that the item slots for weapons are 16, 15 and 14. Therefore, we will need to separate these out from the item list. We can simply do this by using an “if” statement to check to see if the slot attribute is either; 16, 15 or 14.

If the item has the slot number 16, 15 or 14 then we are going to add them to the weapons_list variable. Or if they are not, we are going to add them to the item_list variable.

This is not all though. Each of the items will need to be placed into a holder in this case a <div> tag. They will also need to be constructed so that later when we click on them <div> tags are hidden and only the item stat page is shown.

clip_image002[9]

So to do this, we will use the following code.

 1: if ((curr_item.getAttribute("slot") == "16") || (curr_item.getAttribute("slot") == "14") || (curr_item.getAttribute("slot") == "15")) {
 2: weapons_list += div_item_holder;
 3: weapons_list += '<a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'hide\',\'m_armour\',\'\',\'hide\',\'m_weapons\',\'\',\'show\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'hide\',\'m_talents\',\'\',\'hide\',\'m_viewitem\',\'\',\'show\',\'m_stats_detail\',\'\',\'hide\'), get_item(';
 4: weapons_list += curr_item.getAttribute("id");
 5: weapons_list += ')"><img src="http://wow.ukgl.co.uk/img/items/';
 6: weapons_list += curr_item.getAttribute("icon");
 7: weapons_list += '.gif" width="20" height="20" border="0" /></a></div>';
 8: } else {
 9: item_list += div_item_holder;
 10: item_list += '<a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'hide\',\'m_armour\',\'\',\'show\',\'m_weapons\',\'\',\'hide\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'hide\',\'m_talents\',\'\',\'hide\',\'m_viewitem\',\'\',\'show\',\'m_stats_detail\',\'\',\'hide\'), get_item(';
 11: item_list += curr_item.getAttribute("id");
 12: item_list += ')"><img src="http://wow.ukgl.co.uk/img/items/';
 13: item_list += curr_item.getAttribute("icon");
 14: item_list += '.gif" width="20" height="20" border="0" /></a></div>';
 15: }
 16: };

Now it gets slightly more confusing as we are embedding JavaScript with a JavaScript document as an HTML output which is always crazy.

So to start, we will create a new variable html, and the first thing we’ll do with any HTML page is obviously to tell the browser it is rendering HTML by using the <html> tags and of course followed by <head>.

var html = '';
html += '<html><head>';

That’s the easy part out of the way. Next we’ll need to tell the browser that we are using JavaScript.

html += '<script type="text/javascript">';

Right, we can now start building in all of the dynamic pages to display all of this item and weapons data. To begin with, we will once again define a load of variables each corresponding to the appropriate HTML element document.getElementById(\'item_value4\'). We will have 6 text areas in which the information will reside. Additionally, whilst we do this, we may as well do the same for the user’s stats tabs.

This part of the script will basically empty all of the information that’s was previously in the box and set it to null.

 1: html += 'function tabs() {'; 
 2: html += 'var txt_stat_name = document.getElementById(\'stat_name\');';
 3: html += 'var stat_value0 = document.getElementById(\'stat_value0\');';
 4: html += 'var stat_value1 = document.getElementById(\'stat_value1\');';
 5: html += 'var stat_value2 = document.getElementById(\'stat_value2\');';
 6: html += 'var stat_value3 = document.getElementById(\'stat_value3\');';
 7: html += 'var stat_value4 = document.getElementById(\'stat_value4\');';
 8: html += 'var stat_value5 = document.getElementById(\'stat_value5\');';
 9: html += 'txt_stat_name.innerHTML = "Please select an item.";';
 10: html += 'stat_value0.innerHTML = "";';
 11: html += 'stat_value1.innerHTML = "";';
 12: html += 'stat_value2.innerHTML = "";';
 13: html += 'stat_value3.innerHTML = "";';
 14: html += 'stat_value4.innerHTML = "";';
 15: html += 'stat_value5.innerHTML = "";';
 16: html += 'var txt_item_name = document.getElementById(\'item_name\');';
 17: html += 'var item_value0 = document.getElementById(\'item_value0\');';
 18: html += 'var item_value1 = document.getElementById(\'item_value1\');';
 19: html += 'var item_value2 = document.getElementById(\'item_value2\');';
 20: html += 'var item_value3 = document.getElementById(\'item_value3\');';
 21: html += 'var item_value4 = document.getElementById(\'item_value4\');';
 22: html += 'var item_value5 = document.getElementById(\'item_value5\');';
 23: html += 'txt_item_name.innerHTML = "Please select an item.";';
 24: html += 'item_value0.innerHTML = "";';
 25: html += 'item_value1.innerHTML = "";';
 26: html += 'item_value2.innerHTML = "";';
 27: html += 'item_value3.innerHTML = "";';
 28: html += 'item_value4.innerHTML = "";';
 29: html += 'item_value5.innerHTML = "";';

Now I have talked a lot about this tabbing system. Essentially, it will just hide and show <div> or layers when instructed to.

To do this, we are going to use some real basic JavaScript for simplicity purposes. Like I said, this will basically hide and show layers on our document. We are going to have this as a function so that using:

onclick="tabs('m_home','','hide')

We can either hide or show tabs when necessary.

 1: html += 'var i,p,v,obj,args=tabs.arguments;';
 2: html += 'for (i=0; i<(args.length-2); i+=3) ';
 3: html += 'with (document) if (getElementById && ((obj=getElementById(args[i]))!=null)) { v=args[i+2];';
 4: html += 'if (obj.style) { obj=obj.style; v=(v==\'show\')?\'visible\':(v==\'hide\')?\'hidden\':v; }';
 5: html += 'obj.visibility=v; }';
 6: html += '}';

The next function we are going to create is actually going to pull the data from the second XML page, the detailed items stats one and then display it.

We need to create the function so that every time it’s called with a new item Id, the JavaScript can go away and fetch all of the appropriate data and then organise it into the correct field on the items tab.

To begin with, we are going to be using a new XML sheet located at:

http://wow.ukgl.co.uk/wow_xml.cfm?xml_feed=item_detail&s=EU&i=

And where the “i=” is, that is where we will put in our item Id to be queried.

Again, we are also going to define the variable itemInfo which will be assigned to the XML sheet with the corresponding item Id.

html += 'function get_item(itemId) {';

html += 'var item_xml = environment.getXml("http://wow.ukgl.co.uk/wow_xml.cfm?xml_feed=item_detail&s=EU&i="+itemId);';

html += 'var itemInfo = item_xml.selectSingleNode("/page/itemTooltips/itemTooltip");';

Next, we will once again need to define all of the text areas we will be using to submit the data to.

 1: html += 'var txt_item_name = document.getElementById(\'item_name\');';
 2: html += 'var item_value0 = document.getElementById(\'item_value0\');';
 3: html += 'var item_value1 = document.getElementById(\'item_value1\');';
 4: html += 'var item_value2 = document.getElementById(\'item_value2\');';
 5: html += 'var item_value3 = document.getElementById(\'item_value3\');';
 6: html += 'var item_value4 = document.getElementById(\'item_value4\');';
 7: html += 'var item_value5 = document.getElementById(\'item_value5\');';
 8: html += 'txt_item_name.innerHTML = "Please select an item.";';
 9: html += 'item_value0.innerHTML = "";';
 10: html += 'item_value1.innerHTML = "";';
 11: html += 'item_value2.innerHTML = "";';
 12: html += 'item_value3.innerHTML = "";';
 13: html += 'item_value4.innerHTML = "";';
 14: html += 'item_value5.innerHTML = "";';

In World Of WarCraft, each item is colour coded to represent its level or power. We can also represent this by reading the nodeValue of the overallQualityId on the XML sheet.

clip_image002[11]

I have created the following table to show the breakdown of the overallQualityId and its matching colour.

Quality ID

Colour

6

 

5

 

4

 

3

 

2

 

1

 

So with this in mind, we are able to set the appropriate font colour using a very simple “if” statement and some HTML formatting. Not only this, but the Item name is also inserted.

itemInfo.selectSingleNode("name").firstChild.nodeValue

 1: html += 'if (itemInfo.selectSingleNode("overallQualityId").firstChild.nodeValue == "6") {';
 2: html += 'txt_item_name.innerHTML = "<font color=#FF9900><b>" + itemInfo.selectSingleNode("name").firstChild.nodeValue + "</b></font>";';
 3: html += '} else if (itemInfo.selectSingleNode("overallQualityId").firstChild.nodeValue == "5") {';
 4: html += 'txt_item_name.innerHTML = "<font color=#990099><b>" + itemInfo.selectSingleNode("name").firstChild.nodeValue + "</b></font>";';
 5: html += '} else if (itemInfo.selectSingleNode("overallQualityId").firstChild.nodeValue == "4") {';
 6: html += 'txt_item_name.innerHTML = "<font color=#FF0000><b>" + itemInfo.selectSingleNode("name").firstChild.nodeValue + "</b></font>";';
 7: html += '} else if (itemInfo.selectSingleNode("overallQualityId").firstChild.nodeValue == "3") {';
 8: html += 'txt_item_name.innerHTML = "<font color=#006699><b>" + itemInfo.selectSingleNode("name").firstChild.nodeValue + "</b></font>";';
 9: html += '} else if (itemInfo.selectSingleNode("overallQualityId").firstChild.nodeValue == "2") {';
 10: html += 'txt_item_name.innerHTML = "<font color=#009900><b>" + itemInfo.selectSingleNode("name").firstChild.nodeValue + "</b></font>";';
 11: html += '} else {';
 12: html += 'txt_item_name.innerHTML = "<font color=#000000><b>" + itemInfo.selectSingleNode("name").firstChild.nodeValue + "</b></font>";';
 13: html += '};';

Right, now that we have got the item stats title sorted, we can now go through the XML sheet in more detail to get the XML data for each item.

 1: html += 'if (itemInfo.selectSingleNode("equipData/subclassName").firstChild.nodeValue == null) {';
 2: html += 'item_value0.innerHTML = "Misc";';
 3: html += '} else {';
 4: html += 'item_value0.innerHTML = itemInfo.selectSingleNode("equipData/subclassName").firstChild.nodeValue;';
 5: html += '}';
 6: html += 'if (itemInfo.selectSingleNode("bonusStamina").firstChild.nodeValue == null) {';
 7: html += '} else {';
 8: html += 'item_value1.innerHTML = itemInfo.selectSingleNode("bonusStamina").nodeName + ": " + itemInfo.selectSingleNode("bonusStamina").firstChild.nodeValue;';
 9: html += '};';
 10: html += 'if (itemInfo.selectSingleNode("bonusStrength").firstChild.nodeValue == null) {';
 11: html += '} else {';
 12: html += 'item_value2.innerHTML = itemInfo.selectSingleNode("bonusStrength").nodeName + ": " + itemInfo.selectSingleNode("bonusStrength").firstChild.nodeValue;';
 13: html += '};';
 14: html += 'if (itemInfo.selectSingleNode("armor").firstChild.nodeValue == null) {';
 15: html += '} else {';
 16: html += 'item_value3.innerHTML = itemInfo.selectSingleNode("armor").nodeName + ": " + itemInfo.selectSingleNode("armor").firstChild.nodeValue;';
 17: html += '};';
 18: html += 'if (itemInfo.selectSingleNode("durability").firstChild.nodeValue == null) {';
 19: html += '} else {';
 20: html += 'item_value4.innerHTML = itemInfo.selectSingleNode("durability").nodeName + ": " + itemInfo.selectSingleNode("durability").firstChild.nodeValue;';
 21: html += '};';
 22: html += '};';

Now that the item title is sorted, we can move on to the stats attributes. The stats query the most amount of XML data so it might seem quite hectic but I will try to explain it all as best as I can. Right, in World of WarCraft there are 6 stats classes, these are:

· Base

· Melee

· Defence

· Resistances

· Spell

· Range

clip_image002[13]

Therefore, we will need 6 separate functions to automatically load the information into our static <div>. To do this, we are going to use the same process as before but this time we are using static information.

With Stats base we are going to be calling the following information:

· Strength

· Agility

· Stamina

· Intellect

· Spirit

· Armour

So how do we find this information? It’s all buried in our main XML sheet we just need to know where to look.

Before we get started on the XML front, there are a few things we need to get sorted first. Since we are getting the values in our Stats detail <div> to continually change we are going to make this dynamic. In order to do this we are going to have to re-pass our Server, Realm and character information across in variables and re-query our XML source.

We are going to start by creating a function called statBase with this we are going to assign some function parameters; statGetServer, statGetRealm, statGetCharacter later when we create a link to execute the function we will include the parameters that the user initially provided. Using this information, we will be able to re-query the XML sheet to get the appropriate information regarding the user’s stats. In this first code sample, we have gone ahead and created the function with our parameters and we have created a variable which will connect to our XML data source.

//STAT BASE

html += 'function statBase(statGetServer, statGetRealm, statGetCharacter) {';

html += 'var base_xml = environment.getXml("http://wow.ukgl.co.uk/wow_xml.cfm?s="+statGetServer+"&r="+statGetRealm+"&n="+statGetCharacter);';

Next, we are going to create our second variable baseStats which will navigate the correct node /page/characterInfo/characterTab/baseStats on the XML document.

Then we will have to again setup variables which relate to the elements which are within are stats detail <div> tag.

 1: html += 'var baseStats = base_xml.selectSingleNode("/page/characterInfo/characterTab/baseStats");';
 2: html += 'var txt_stat_name = document.getElementById(\'stat_name\');';
 3: html += 'var stat_value0 = document.getElementById(\'stat_value0\');';
 4: html += 'var stat_value1 = document.getElementById(\'stat_value1\');';
 5: html += 'var stat_value2 = document.getElementById(\'stat_value2\');';
 6: html += 'var stat_value3 = document.getElementById(\'stat_value3\');';
 7: html += 'var stat_value4 = document.getElementById(\'stat_value4\');';
 8: html += 'var stat_value5 = document.getElementById(\'stat_value5\');';

Now that we have set up the fields that will hold our information regarding the characters statistics, we can look at connecting to our XML sheet and populate our stats page.

StatsBase, consist of 6 stats, these are:

· Strength

· Agility

· Stamina

· Intellect

· Spirit

· Armour

These stats will of course need values assigned to them in order for them to make any sense. As you can work out from the code below, we are using a simple string to combine both stat name and stat value. So here is an example string.

“Strength: "+baseStats.selectSingleNode("strength").getAttribute("effective");

We start by defining the stat name in this case “Strength”. Next we will need to pull the appropriate XML data from our XML data source. We have already defined baseStats which navigates to the XML node /page/characterInfo/characterTab/baseStats now that we have navigated to this node block we need to drill into it in more detail. So here is the XML data we get when querying our baseStats variable.

 1: <baseStats>
 2: <strength attack="650" base="150" block="16" effective="335"/>
 3: <agility armor="358" attack="-1" base="91" critHitPercent="6.56" effective="179"/>
 4: <stamina base="135" effective="590" health="5720" petBonus="-1"/>
 5: <intellect base="28" critHitPercent="-1.00" effective="28" mana="-1" petBonus="-1"/>
 6: <spirit base="53" effective="53" healthRegen="32" manaRegen="-1"/>
 7: <armor base="7823" effective="7823" percent="42.56" petBonus="-1"/>
 8: </baseStats>

Already looking at this, we can see the 6 stat names. We are also given multiple attributes to deal with; we don’t need all of this information so we only need to select which information is relevant. You can probably see from the code sample which attributes we are selecting.

 

Node Name

Attribute

Strength

Effective

Agility

Effective

Stamina

Effective

Intellect

Effective

Spirit

Effective

Armour

Effective

So from this table , you can easily see that we are selecting the effective attribute from all of our stat nodes. Let’s take a look at this in full.

 1: html += 'txt_stat_name.innerHTML = "<b>Base</b>";';
 2: html += 'stat_value0.innerHTML = "Strength: "+baseStats.selectSingleNode("strength").getAttribute("effective");';
 3: html += 'stat_value1.innerHTML = "Agility: "+baseStats.selectSingleNode("agility").getAttribute("effective");';
 4: html += 'stat_value2.innerHTML = "Stamina: "+baseStats.selectSingleNode("stamina").getAttribute("effective");';
 5: html += 'stat_value3.innerHTML = "Intellect: "+baseStats.selectSingleNode("intellect").getAttribute("effective");';
 6: html += 'stat_value4.innerHTML = "Spirit: "+baseStats.selectSingleNode("spirit").getAttribute("effective");';
 7: html += 'stat_value5.innerHTML = "Armor: "+baseStats.selectSingleNode("armor").getAttribute("effective");';
 8: html += '};';

So from the code above, we are using our stat_value5.innerHTML to set which <div> tag we will be using and then we are creating a string to place inside that <div> tag.

We will more or less do the same for the next 6 stats.

Here we have our melee stat which will be using the following attributes:

Node Name

Attribute

Weapon Skill

Value

Damage

Min / max

Speed

mainHandDamage.speed / offHandDamage.speed

Power

Effective

Hit Rating

value

Crit Chance

percent

Now in most cases with Melee, our strings will contain more than one stat value, this doesn’t really differ from what we have been doing already we are just adding another XML node value onto the end of our existing string.

 1: //STAT MELEE
 2: html += 'function statMelee(statGetServer, statGetRealm, statGetCharacter) {'; 
 3: html += 'var base_xml = environment.getXml("http://wow.ukgl.co.uk/wow_xml.cfm?s="+statGetServer+"&r="+statGetRealm+"&n="+statGetCharacter);';
 4: html += 'var melee = base_xml.selectSingleNode("/page/characterInfo/characterTab/melee");';
 5:  
 6: html += 'var txt_stat_name = document.getElementById(\'stat_name\');';
 7: html += 'var stat_value0 = document.getElementById(\'stat_value0\');';
 8: html += 'var stat_value1 = document.getElementById(\'stat_value1\');';
 9: html += 'var stat_value2 = document.getElementById(\'stat_value2\');';
 10: html += 'var stat_value3 = document.getElementById(\'stat_value3\');';
 11: html += 'var stat_value4 = document.getElementById(\'stat_value4\');';
 12: html += 'var stat_value5 = document.getElementById(\'stat_value5\');';
 13: 
 14: html += 'txt_stat_name.innerHTML = "<b>Melee</b>";';
 15: html += 'stat_value0.innerHTML = "Weapon Skill: "+melee.selectSingleNode("mainHandWeaponSkill").getAttribute("value");';
 16: html += 'stat_value1.innerHTML = "Damage: "+melee.selectSingleNode("mainHandDamage").getAttribute("min")+" - "+melee.selectSingleNode("mainHandDamage").getAttribute("max");';
 17: html += 'stat_value2.innerHTML = "Speed: "+melee.selectSingleNode("mainHandDamage").getAttribute("speed")+" / "+melee.selectSingleNode("offHandDamage").getAttribute("speed");';
 18: html += 'stat_value3.innerHTML = "Power: "+melee.selectSingleNode("power").getAttribute("effective");';
 19: html += 'stat_value4.innerHTML = "Hit Rating: "+melee.selectSingleNode("hitRating").getAttribute("value");';
 20: html += 'stat_value5.innerHTML = "Crit Chance: "+melee.selectSingleNode("critChance").getAttribute("percent");'; 
 21: html += '};';

Here is our stat defence information; again here is stat attribute table.

Node Name

Attribute

Armour

Base

Defence

Value

Dodge

percent

Parry

percent

Block

Percent

Resilience

value

Again here is the code for our defence stats.

 1: //STAT DEFENSE
 2: 
 3: html += 'function statDefense(statGetServer, statGetRealm, statGetCharacter) {';
 4: html += 'var base_xml = environment.getXml("http://wow.ukgl.co.uk/wow_xml.cfm?s="+statGetServer+"&r="+statGetRealm+"&n="+statGetCharacter);';
 5: html += 'var defense = base_xml.selectSingleNode("/page/characterInfo/characterTab/defenses");';
 6: html += 'var txt_stat_name = document.getElementById(\'stat_name\');';
 7: html += 'var stat_value0 = document.getElementById(\'stat_value0\');';
 8: html += 'var stat_value1 = document.getElementById(\'stat_value1\');';
 9: html += 'var stat_value2 = document.getElementById(\'stat_value2\');';
 10: html += 'var stat_value3 = document.getElementById(\'stat_value3\');';
 11: html += 'var stat_value4 = document.getElementById(\'stat_value4\');';
 12: html += 'var stat_value5 = document.getElementById(\'stat_value5\');';
 13: html += 'txt_stat_name.innerHTML = "<b>Defence</b>";';
 14: html += 'stat_value0.innerHTML = "Armour: "+defense.selectSingleNode("armor").getAttribute("base");';
 15: html += 'stat_value1.innerHTML = "Defence: "+defense.selectSingleNode("defense").getAttribute("value");';
 16: html += 'stat_value2.innerHTML = "Dodge: "+defense.selectSingleNode("dodge").getAttribute("percent");';
 17: html += 'stat_value3.innerHTML = "Parry: "+defense.selectSingleNode("parry").getAttribute("percent");';
 18: html += 'stat_value4.innerHTML = "Block: "+defense.selectSingleNode("block").getAttribute("percent");';
 19: html += 'stat_value5.innerHTML = "Resilience: "+defense.selectSingleNode("resilience").getAttribute("value");'; 
 20: html += '};';

Here is the information for our resistances stats:

Node Name

Attribute

Arcane

Value

Fire

Value

Frost

Value

Holy

Value

Nature

Value

Shadow

Value

 1: //STAT RESISTANCES
 2:  
 3: html += 'function statResistances(statGetServer, statGetRealm, statGetCharacter) {'; 
 4: html += 'var base_xml = environment.getXml("http://wow.ukgl.co.uk/wow_xml.cfm?s="+statGetServer+"&r="+statGetRealm+"&n="+statGetCharacter);';
 5: html += 'var resistances = base_xml.selectSingleNode("/page/characterInfo/characterTab/resistances");';
 6: html += 'var txt_stat_name = document.getElementById(\'stat_name\');';
 7: html += 'var stat_value0 = document.getElementById(\'stat_value0\');';
 8: html += 'var stat_value1 = document.getElementById(\'stat_value1\');';
 9: html += 'var stat_value2 = document.getElementById(\'stat_value2\');';
 10: html += 'var stat_value3 = document.getElementById(\'stat_value3\');';
 11: html += 'var stat_value4 = document.getElementById(\'stat_value4\');';
 12: html += 'var stat_value5 = document.getElementById(\'stat_value5\');';
 13: html += 'txt_stat_name.innerHTML = "<b>Resistances</b>";';
 14: html += 'stat_value0.innerHTML = "Arcane: "+resistances.selectSingleNode("arcane").getAttribute("value");';
 15: html += 'stat_value1.innerHTML = "Fire: "+resistances.selectSingleNode("fire").getAttribute("value");';
 16: html += 'stat_value2.innerHTML = "Frost: "+resistances.selectSingleNode("frost").getAttribute("value");';
 17: html += 'stat_value3.innerHTML = "Holy: "+resistances.selectSingleNode("holy").getAttribute("value");';
 18: html += 'stat_value4.innerHTML = "Nature: "+resistances.selectSingleNode("nature").getAttribute("value");';
 19: html += 'stat_value5.innerHTML = "Shadow: "+resistances.selectSingleNode("shadow").getAttribute("value");'; 
 20: html += '};';
 21:  

Here is the information for our spell stats:

Node Name

Attribute

Bonus Damage

Value

Bonus Healing

Value

Hit Rating

Value

Crit Chance

percent

Penetration

Value

Mana Regen

casting

 1: //STAT SPELL
 2: html += 'function statSpell(statGetServer, statGetRealm, statGetCharacter) {'; 
 3: html += 'var base_xml = environment.getXml("http://wow.ukgl.co.uk/wow_xml.cfm?s="+statGetServer+"&r="+statGetRealm+"&n="+statGetCharacter);';
 4: html += 'var bonusDamage = base_xml.selectSingleNode("/page/characterInfo/characterTab/spell/bonusDamage");';
 5: html += 'var bonusHealing = base_xml.selectSingleNode("/page/characterInfo/characterTab/spell/bonusHealing");';
 6: html += 'var hitRating = base_xml.selectSingleNode("/page/characterInfo/characterTab/spell/hitRating");';
 7: html += 'var critChance = base_xml.selectSingleNode("/page/characterInfo/characterTab/spell/critChance");';
 8: html += 'var penetration = base_xml.selectSingleNode("/page/characterInfo/characterTab/spell/penetration");';
 9: html += 'var manaRegen = base_xml.selectSingleNode("/page/characterInfo/characterTab/spell/manaRegen");';
 10:  
 11: html += 'var txt_stat_name = document.getElementById(\'stat_name\');';
 12: html += 'var stat_value0 = document.getElementById(\'stat_value0\');';
 13: html += 'var stat_value1 = document.getElementById(\'stat_value1\');';
 14: html += 'var stat_value2 = document.getElementById(\'stat_value2\');';
 15: html += 'var stat_value3 = document.getElementById(\'stat_value3\');';
 16: html += 'var stat_value4 = document.getElementById(\'stat_value4\');';
 17: html += 'var stat_value5 = document.getElementById(\'stat_value5\');';
 18: html += 'txt_stat_name.innerHTML = "<b>Spell</b>";';
 19: html += 'stat_value0.innerHTML = "Bonus Damage: "+bonusDamage.selectSingleNode("arcane").getAttribute("value");';
 20: html += 'stat_value1.innerHTML = "Bonus Healing: "+bonusHealing.getAttribute("value");';
 21: html += 'stat_value2.innerHTML = "Hit Rating: "+hitRating.getAttribute("value");';
 22: html += 'stat_value3.innerHTML = "Crit Chance: "+critChance.selectSingleNode("arcane").getAttribute("percent");';
 23: html += 'stat_value4.innerHTML = "Penetration: "+penetration.getAttribute("value");';
 24: html += 'stat_value5.innerHTML = "Mana Regen: "+manaRegen

Last but not least, our Ranged stats;

Node Name

Attribute

Weapon Skill

Value

Damage

Min / max

Speed

Value

Power

Effective

Hit Rating

Value

Crit Chance

percent

 1: //STAT RANGED
 2: html += 'function statRanged(statGetServer, statGetRealm, statGetCharacter) {'; 
 3: html += 'var base_xml = environment.getXml("http://wow.ukgl.co.uk/wow_xml.cfm?s="+statGetServer+"&r="+statGetRealm+"&n="+statGetCharacter);';
 4: html += 'var ranged = base_xml.selectSingleNode("/page/characterInfo/characterTab/ranged");';
 5: html += 'var txt_stat_name = document.getElementById(\'stat_name\');';
 6: html += 'var stat_value0 = document.getElementById(\'stat_value0\');';
 7: html += 'var stat_value1 = document.getElementById(\'stat_value1\');';
 8: html += 'var stat_value2 = document.getElementById(\'stat_value2\');';
 9: html += 'var stat_value3 = document.getElementById(\'stat_value3\');';
 10: html += 'var stat_value4 = document.getElementById(\'stat_value4\');';
 11: html += 'var stat_value5 = document.getElementById(\'stat_value5\');';
 12: html += 'txt_stat_name.innerHTML = "<b>Ranged</b>";';
 13: html += 'stat_value0.innerHTML = "Weapon Skill: "+ranged.selectSingleNode("weaponSkill").getAttribute("value");';
 14: html += 'stat_value1.innerHTML = "Damage: "+ranged.selectSingleNode("damage").getAttribute("min")+" / "+ranged.selectSingleNode("damage").getAttribute("max");';
 15: html += 'stat_value2.innerHTML = "Speed: "+ranged.selectSingleNode("speed").getAttribute("value");';
 16: html += 'stat_value3.innerHTML = "Power: "+ranged.selectSingleNode("power").getAttribute("effective");';
 17: html += 'stat_value4.innerHTML = "Hit Rating: "+ranged.selectSingleNode("hitRating").getAttribute("value");';
 18: html += 'stat_value5.innerHTML = "Crit Chance: "+ranged.selectSingleNode("critChance").getAttribute("percent");'; 
 19: html += '};';
 20: html += '</script>';
 21: html += '</head>';

Ok, we have nearly finished! It is now just a case of bringing everything together into one final HTML page. As I mentioned before, there are 6 tabs with two additional ones more information on either items or stats. We now need to create these 8, but first just to re-cap.

  1. · Home
  2. · Armour
    • Details tab
  3. · Weapons
    • Details tab
  4. · PVP
  5. · Stats
    • Details tab

· Talents

I know there 9 there but we can use the Armour and Weapons Detail tabs as one as they are essentially displaying the same information.

We are going to construct each tab in the same way.

 1: html += '<body onload="tabs(\'m_home\',\'\',\'show\',\'m_armour\',\'\',\'hide\',\'m_weapons\',\'\',\'hide\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'hide\',\'m_talents\',\'\',\'hide\',\'m_viewitem\',\'\',\'hide\',\'m_stats_detail\',\'\',\'hide\')">';
 2: html += '<div align="center" style="height:100%; width:100%; background-color:#000000;">';

Earlier we created a loop to query all of the items. These items were broken up into two groups and assigned to a variable. All we need to do for the amour tab is just include this variable.

Again to note, each tab or layer we create from now on will always have an Id so that we can relate to it through the function we wrote earlier. It will also contain a usr_picture which holds the users avatar this will be on all tabs. Lastly, each tab will also have the variable navigation which contains the navigation for the entire application.

 1: //ARMOUR
 2: html += '<div id="m_armour" style="';
 3: html += fl;
 4: html += '">';
 5: html += '<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td>';
 6: html += usr_picture;
 7: html += '</td><td colspan="2" align="left">';
 8: html += items_padding;
 9: html += item_list;
 10: html += '</div></td><tr>';
 11: html += navigation;
 12: html += '</tr>';
 13: html += '</table>';
 14: html += '</div>';

Our weapons tab is going to be the same as our amour tab. This tab is just going to simply include the pre-generated HTML we had earlier when creating the XML loop - this just needs to be inserted.

 1: //WEAPONS
 2: html += '<div id="m_weapons" style="';
 3: html += fl;
 4: html += '">';
 5: html += '<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td>';
 6: html += usr_picture;
 7: html += '</td><td colspan="2" align="left">';
 8: html += items_padding;
 9: html += weapons_list;
 10: html += '</div></td></tr><tr>';
 11: html += navigation;
 12: html += '</tr>';
 13: html += '</table>';
 14: html += '</div>';

In order to get all of our stats written dynamically, we are going to need 6 <div> tags to hold the information in. With correspondence to what was written above these 6 <div> fields must be named:

· item_value0

· item_value1

· item_value2

· item_value3

· item_value4

· item_value5

Therefore, the function we programmed earlier, can insert the correct information into these 6 text boxes. I have assembled this information into a table.

 1: //VIEW ITEM STATS
 2: html += '<div id="m_viewitem" style="';
 3: html += m_viewitem;
 4: html += '">';
 5: html += '<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td colspan="3"><div style="';
 6: html += txt12;
 7: html += '" id="item_name">Please select an item.</div></td></tr><tr><td><div style="';
 8: html += txt9;
 9: html += '" id="item_value0"></div></td><td><div style="';
 10: html += txt9;
 11: html += '" id="item_value2"></div></td><td><div style="';
 12: html += txt9;
 13: html += '" id="item_value4"></div></td></tr><tr><td><div style="';
 14: html += txt9;
 15: html += '" id="item_value1"></div></td><td><div style="';
 16: html += txt9;
 17: html += '" id="item_value3"></div></td><td><div style="';
 18: html += txt9;
 19: html += '" id="item_value5"></div></td></tr></table>';
 20: html += '</div>';

Right, although stats look complex, it’s fairly simple. All we are doing is creating 6 links for our 6 stats pages and each of these links needs an “onClick” command to run our JavaScript function.

 1: //STATS
 2: html += '<div id="m_stats" style="';
 3: html += fl;
 4: html += '">';
 5: html += '<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td>';
 6: html += usr_picture;
 7: html += '</td><td colspan="2" valign="bottom" style="padding-bottom: 7px;">';
 8: html += stxt10;
 9: html += '<a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'hide\',\'m_armour\',\'\',\'hide\',\'m_weapons\',\'\',\'hide\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'show\',\'m_show\',\'\',\'hide\',\'m_viewitem\',\'\',\'hide\',\'m_stats_detail\',\'\',\'show\'), statBase(\''+getServer+'\', \''+getRealm+'\', \''+getCharacter+'\')">Base</a> | <a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'hide\',\'m_armour\',\'\',\'hide\',\'m_weapons\',\'\',\'hide\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'show\',\'m_show\',\'\',\'hide\',\'m_viewitem\',\'\',\'hide\',\'m_stats_detail\',\'\',\'show\'), statMelee(\''+getServer+'\', \''+getRealm+'\', \''+getCharacter+'\')">Melee</a> | <a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'hide\',\'m_armour\',\'\',\'hide\',\'m_weapons\',\'\',\'hide\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'show\',\'m_show\',\'\',\'hide\',\'m_viewitem\',\'\',\'hide\',\'m_stats_detail\',\'\',\'show\'), statDefense(\''+getServer+'\', \''+getRealm+'\', \''+getCharacter+'\')">Defense</a> | <a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'hide\',\'m_armour\',\'\',\'hide\',\'m_weapons\',\'\',\'hide\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'show\',\'m_show\',\'\',\'hide\',\'m_viewitem\',\'\',\'hide\',\'m_stats_detail\',\'\',\'show\'), statResistances(\''+getServer+'\', \''+getRealm+'\', \''+getCharacter+'\')">Resistances</a> | <a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'hide\',\'m_armour\',\'\',\'hide\',\'m_weapons\',\'\',\'hide\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'show\',\'m_show\',\'\',\'hide\',\'m_viewitem\',\'\',\'hide\',\'m_stats_detail\',\'\',\'show\'), statSpell(\''+getServer+'\', \''+getRealm+'\', \''+getCharacter+'\')">Spell</a> | <a style="cursor:pointer;" onclick="tabs(\'m_home\',\'\',\'hide\',\'m_armour\',\'\',\'hide\',\'m_weapons\',\'\',\'hide\',\'m_pvp\',\'\',\'hide\',\'m_stats\',\'\',\'show\',\'m_show\',\'\',\'hide\',\'m_viewitem\',\'\',\'hide\',\'m_stats_detail\',\'\',\'show\'), statRanged(\''+getServer+'\', \''+getRealm+'\', \''+getCharacter+'\')">Ranged</a>';
 10: html += font_close;
 11: html += '</td></tr><tr>';
 12: html += navigation;
 13: html += '</tr>';
 14: html += '</table>';
 15: html += '</div>';

Again, like the items, we want to create a layer that will hold 6 <div> fields so that we can insert our dynamic values from our stats functions.

 1: //VIEW ITEM STATS
 2: html += '<div id="m_stats_detail" style="';
 3: html += m_stats_detail;
 4: html += '">';
 5: html += '<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td colspan="3"><div style="';
 6: html += txt12_b;
 7: html += '" id="stat_name">Please select an item.</div></td></tr><tr><td><div style="'
 8: html += txt9;
 9: html += '" id="stat_value0"></div></td><td><div style="'
 10: html += txt9;
 11: html += '" id="stat_value2"></div></td><td><div style="'
 12: html += txt9;
 13: html += '" id="stat_value4"></div></td></tr><tr><td><div style="'
 14: html += txt9;
 15: html += '" id="stat_value1"></div></td><td><div style="'
 16: html += txt9;
 17: html += '" id="stat_value3"></div></td><td><div style="'
 18: html += txt9;
 19: html += '" id="stat_value5"></div></td></tr></table>';
 20: html += '</div>';

Right, we are now getting onto our simple and static layers. The first is PVP. This tab will need to show the players PVP stats. These PVP stats consist of the players PVP title and their life time honourable kills.

So, we are going to once again start by creating a simple <div> layer that will hold our information. We will only need to query our XML sheet for two values. As I said before, we will need the players PVP tile and life time honourable kills. So where do we find this information? We defined the variable knownTitles early on in the application this basically relates to the XML <page><characterInfo><characterTab><knownTitles> then if we look at our XML reference:

<knownTitles>
<title value="Scout"/>
</knownTitles>

We can now see the XML layout. As we can see from the <title> node, we will need to select the attribute value in order to get the players PVP title. Similarly, we will also need to get the players life time honourable kills. Looking at our XML again, if we navigate to the <pvp> node we can already see that we need to select the attribute value from the <lifetimehonorablekills> node.

<pvp>
<lifetimehonorablekills value="5399"/>
<arenacurrency value="53"/>
</pvp>

Right, now that we know where we are getting our information from, we can go ahead and write our tab. We will also need to include an if statement as the PVP tile can equal a null value. If this is the case then we need to set the players PVP tile as “Player”.

 1: //PVP
 2: html += '<div id="m_pvp" style="';
 3: html += fl;
 4: html += '">';
 5: html += '<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td>';
 6: html += usr_picture;
 7: html += '</td><td colspan="2">';
 8: html += stxt16b;
 9: if (knownTitles.getAttribute("value") == '') {
 10: html += '<b>Player</b>';
 11: } else {
 12: html += knownTitles.getAttribute("value");
 13: }
 14: html += font_close;
 15: html += '<br />';
 16: html += stxt10b;
 17: html += 'Lifetime Honourable Kills : ';
 18: html += pvp.getAttribute("value");
 19: html += font_close;
 20: html += '</td></tr><tr>';
 21: html += navigation;
 22: html += '</tr>';
 23: html += '</table>';
 24: html += '</div>';

Now that we have done that, we more or less need to do the same again for the talents tab. This time we are grabbing our three static values from our classId code that we defined earlier on. Simply put, we are going to create a table with three columns and two rows. The top three columns will contain our pre-defined values based on our characters classId. On the row below, we are going to have our three stats. This information will be taken from our XML sheet. Here we have our XML reference.

<talentSpec treeOne="41" treeThree="0" treeTwo="20"/>

As you can see already, we will be extracting the three values from the attributes; treeOne, treeThree, treeTwo as we did before, we are again going to query those three values as you can see from below.

 1: //TALENTS
 2: html += '<div id="m_talents" style="';
 3: html += fl;
 4: html += '">';
 5: html += '<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td>';
 6: html += usr_picture;
 7: html += '</td><td><table width="100%" border="0" cellspacing="0" cellpadding="1"><tr><td>';
 8: html += stxt12b;
 9: html += talent1;
 10: html += font_close;
 11: html += '</td><td>';
 12: html += stxt12b;
 13: html += talent2;
 14: html += font_close;
 15: html += '</td><td>';
 16: html += stxt12b;
 17: html += talent3;
 18: html += font_close;
 19: html += '</td></tr><tr><td>';
 20: html += stxt12;
 21: html += talentSpec.getAttribute("treeOne");
 22: html += font_close;
 23: html += '</td><td>';
 24: html += stxt12;
 25: html += talentSpec.getAttribute("treeTwo");
 26: html += font_close;
 27: html += '</td><td>';
 28: html += stxt12;
 29: html += talentSpec.getAttribute("treeThree");
 30: html += font_close;
 31: html += '</td></tr></table></td></tr><tr>';
 32: html += navigation;
 33: html += '</tr>';
 34: html += '</table>';
 35: html += '</div>';

Lastly, our final tab! We are nearly at the end of our application now. This tab is the main tab. This will be the first tab to be loaded when the application is run and consequently contains the most information. This tab will get information from multiple XML nodes. I am going to break this tab down to make it easier to understand what’s going on. To begin with, as usual we are going to start off our layer as usual.

 1: //HOME
 2: html += '<div id="m_home" style="';
 3: html += fl;
 4: html += '">';
 5: html += '<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td>';
 6: html += usr_picture;
 7: html += '</td><td><table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><td>';

Next, we are going to insert our first two values, these values will tell us the character Faction and then the characters class. Now, the characters Faction has already been defined using the variable char_class however, we will need to get the characters class from our XML which is not statically defined. We are going to use our character variable to fetch the appropriate character XML nodes.

 1: <character battleGroup="Reckoning" charUrl="r=Moonglade&amp;n=Raymar" class="Warrior" classId="1" faction="Horde" factionId="1" gender="Male" genderId="0" guildName="Temper" guildUrl="r=Moonglade&amp;n=Temper&amp;p=1" lastModified="30 September 2007" level="70" name="Raymar" race="Tauren" raceId="6" realm="Moonglade" title="">

Here, we have the values for our character XML node. Looking at this, we can already see our class attribute which is the one we will be querying. So let’s take a look at our JavaScipt.

 1: // Faction / Class
 2: html += stxt12b;
 3: html += char_class;
 4: html += ' / ';
 5: html += character.getAttribute("class"); 
 6: html += font_close;
 7: html += '</td></tr><tr><td>';

So, simply, we are just creating which is combing both of these two values, separated by a ‘/’. Next we are going to inset the characters name. Again, this is using the same XML node as the characters faction. This time we will be using the attribute name.

// Name

html += stxt16b;
html += character.getAttribute("name");
html += font_close;
html += '</td></tr>';

On our next row of our table, we are going to define our characters guild. We are also going to be using another if statement to check to see if the character is in fact in a guild. If they are in a guild, then we are going to create a row for the data to rest in, if not, then the row will be skipped. Again, we will be using our character XML node. This time however, we will be querying the attribute guildName.

 1: // Guild
 2: if (character.getAttribute("guildName") != "") {
 3: html += '<tr><td>';
 4: html += stxt12b;
 5: html += character.getAttribute("guildName");
 6: html += font_close;
 7: html += '</td></tr>';
 8: };
 9: html += '</table>';

On the last row of our table, we are defining the server that the user is playing on. Again this time, we will be using both a static and value queried from our XML sheet. On this row, we will be creating a string which will basically display the user’s location EU/US and the World of WarCraft Server they play on. The server, EU/US is already defined, this value is set by the user when they are defining their characters information so we can just include the variable getServer, we will also need to get the realm from our XML document. We could use the Realm defined by the user but where’s the fun in that? We will once again be using the character XML node and querying the realm attribute.

// Server

html += stxt12b;
html += getServer;
html += ' - ';

html += character.getAttribute("realm");
html += font_close;

// Server

html += stxt12b;
html += getServer;
html += ' - ';

html += character.getAttribute("realm");
html += font_close;

We are now going to move onto the right hand side of our table. This side will contain both the users health level and their second bar; MANA, ENERGY or RAGE and lastly a field stating when they were last online. The first bar is health; this will contain a value taken from our characterBars variable. Our second bar is defined by our classId variables and was defined earlier on consequently, the values for this will also be retrieved off of the XML sheet along with the players “last online” value. Let’s take a look at our characterBars XML node.

<characterBars>
<health effective="10672"/>
<secondBar casting="-1" effective="100" notCasting="-1" perFive="-1" type="r"/>
</characterBars>

So, as we can see here from our XML node, we will be using the effective attribute for our characters health information. We will also be using effective attribute for the second bar as well. Lastly, we will be using the lastModified attribute from the character XML node which will give us our last online information. With this in mind, here is the JavaScript for the first bar, HEALTH.

 1: // Health
 2: html += '</td><td><table width="100%" border="0" cellspacing="0" cellpadding="2"><tr><td>';
 3: html += stxt10b;
 4: html += 'HEALTH';
 5: html += font_close;
 6: html += '</td><td>';
 7: html += '<div style="height:11; width:153; background:#000000 url(http://wow.ukgl.co.uk/img/popfly/bars/blue.gif) no-repeat center; background-position:top; text-align:center;">';
 8: html += stxt10bw; 
 9: html += characterBars.selectSingleNode("health").getAttribute("effective");
 10: html += font_close;
 11: html += '</div>';
 12: html += '</td></tr><tr><td>';

Now that the health is defined, we can move onto bar2. As I have said, bar2 is defined by the user’s characters classId. As I have already said, there are three possibilities for bar2. I have created the following table with the three possibilities for bar2. Each of these bars also has their own colour this will also be used to get an image for bar2.

RAGE

 

MANA

 

ENERGY

 

Once again, here is the code we have to generate both bar2 based on the characters class.

 1: // Bar2
 2: html += stxt10b;
 3: html += bar2name;
 4: html += font_close;
 5: html += '</td><td>';
 6: html += '<div style="height:11; width:153; background:#000000 url(http://wow.ukgl.co.uk/img/popfly/bars/';
 7: html += bar2colour; 
 8: html += '.gif) no-repeat center; background-position:top; text-align:center;">';
 9: html += stxt10bw; 
 10: html += characterBars.selectSingleNode("secondBar").getAttribute("effective");
 11: html += font_close;
 12: html += '</div>';
 13: html += '</td></tr><tr><td colspan="2">';

Lastly, we need to wrap-up all of the open tags and insert our last online information.

 1: // Last Online
 2: html += stxt10;
 3: html += 'Last Online : ';
 4: html += character.getAttribute("lastModified");
 5: html += font_close;
 6: html += '</td></tr></table></td></tr><tr>';
 7: html += navigation;
 8: html += '</tr>';
 9: html += '</table>';
 10: html += '</div>';

Lastly, we are going to finish up writing the entire application by ending it with these last three lines of code. Firstly, we are obviously going to close our open HMTL</div></div></body></html> tags . Then we are going to tell the Silverlight application to output the HTML we have written. Finally we will close the application.

html += '</div></div></body></html>';
environment.addHtmlWithScript(html);
};

Additionally, we are also going to add the following function to tell Silverlight to run.

ukgl_wow.prototype.initialize = function() {
};

Please feel free to download the source examples and modify/distribute as you feel necessary. If you make changes that you feel I should take a look at/use please email them to me.

clip_image002[15]

Next Steps

As with any program, it is never complete, as you can see there is a load of XML that can still be used. Not only this, but there are still sheets and sheets of XML data on the World of WarCraft Website that can still be used such as guild data. In fact, you could move away from a signature and program the entire World Of WarCraft Amory yourself for you own website, including all your guild members and information.

Conclusion

So, what have we learnt? We have learnt how to dynamically load XML using JavaScript or using AJAX on a very low level basis. We have learnt how to understand and read XML using JavaScript, we have also learnt how to use functions in JavaScript to query different sets of data. But most importantly, you now have some knowledge of the ins and outs of Microsoft’s Popfly and how to setup and create your own block. I hope you will be able to take away something from this article. Lastly, if you have any questions or require support feel free to contact me through my blog at http://hughneale.com.

Follow the Discussion

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.