This news feed uses the WebClient() class that is built into Microsoft's
.net framework to download the contents of an external file. The contents can
then be parsed and displayed locally. Here is the code we are using:
===========================================================================
<%@ Import NameSpace="System" %>
<%@ Import NameSpace="System.Net" %>
<%@ Import NameSpace="System.IO" %>
<%@ Import NameSpace="System.Text.RegularExpressions" %>
<script language="C#" runat="server">
string _path =
"http://www.macromedia.com/desdev/resources/macromedia_resources.xml";
public void Page_Load(Object sender, EventArgs e) {
getData(_path);
}
protected void getData(string url){
string _url = "";
string _urlAry = "";
string _desc = "";
string _descAry = "";
string _titleAry = "";
WebClient request = new WebClient();
Stream s = request.OpenRead(url);
StreamReader sr = new StreamReader(s);
Regex myRegex =
new Regex(@"(<url>.*</url>)|(<title>.*</title>)");
MatchCollection mc = myRegex.Matches(sr.ReadToEnd());
foreach (Match m in mc){
if (m.Value.IndexOf("url") > 0){
_url = m.Value;
_url = _url.Replace("<url>","");
_url = _url.Replace("</url>","");
_urlAry += _url + "|";
} else {
_desc = m.Value;
_desc = _desc.Replace("<title>","");
_desc = _desc.Replace("</title>","");
_descAry += _desc + "|";
}
}
_descAry = _descAry.Substring(0,_descAry.Length-1);
_urlAry = _urlAry.Substring(0,_urlAry.Length-1);
Response.Write
("theUrls="+Server.UrlEncode(_urlAry)+"&theTitles="+Server.UrlEncode(_descAry));
}
</script>
====================================================
Now let's break this up into sections and take a closer look at what is going on:
These are the namespaces that hold the classes we are using to make this application.
<%@ Import NameSpace="System" %>
<%@ Import NameSpace="System.Net" %>
<%@ Import NameSpace="System.IO" %>
<%@ Import NameSpace="System.Text.RegularExpressions" %>
The language to use is C# and the location to run this script
is on the server. When declaring variables in C#, you must specify a data type.
The variable "_path" is declared as a string. The function Page_Load will run
whatever functions are inside it when the page loads.
<script language="C#" runat="server">
string _path =
"http://www.macromedia.com/desdev/resources/macromedia_resources.xml";
public void Page_Load(Object sender, EventArgs e) {
getData(_path);
}
This is the getData() function and inside it is the variable being passed in (url).
First, we initialize the variables being used in the function. Next we create a new instance
of the WebClient class and use the stream variable "s" to hold the data that is
contained in the OpenRead() method of the WebClient class. The StreamReader reads the
Stream variable "s".
myRegex is a regular expression pattern that is being used to look for the fields we want
in the xml data now stored in the StreamReader. This is a simple pattern that is looking for
the opening and closing "<url>" and "<title>" tags and the string contents inbetween.
Next, we use the MatchCollection to find any matches inside the StreamReader using passing through
the file using the ReadToEnd() method of the StreamReader.
protected void getData(string url){
string _url = "";
string _urlAry = "";
string _desc = "";
string _descAry = "";
string _titleAry = "";
WebClient request = new WebClient();
Stream s = request.OpenRead(url);
StreamReader sr = new StreamReader(s);
Regex myRegex =
new Regex(@"(<url>.*</url>)|(<title>.*</title>)");
MatchCollection mc = myRegex.Matches(sr.ReadToEnd());
Now that we have all the matches stored in the MatchCollection, we can loop through
check to see whether or not it's an "<url>" or a "<title>" tag. No matter which it ends
up being, we transfer the Match value to the variable "_url" or "_title". Then the Replace()
function will take each instance of either tag and replace it with nothing. That variable is the
concatenated to the array variable and seperated with the straight piping ("|"). This will have the
array looking something like this:
_urlAry = "value1|value2|value3|"
Since we are left with an extra piping after the last variable has be added to the array, using the Substring()
function will remove it. There are two arguments to the Substring function. Where to start and where to end.
_descAry.Substring(0,_descAry.Length -1) states the we want the Substring to start at the first character in the
string and go the whole length of the string but minus one character. After that has been done for both arrays,
the only thing left is to write the variables being sent to Flash (theUrls and theTitles), and give them their
values. To ensure that the values don't contain any characters that Flash or the browser might get confused with,
the values are wrapped in the server method - Server.UrlEncode();
foreach (Match m in mc){
if (m.Value.IndexOf("url") > 0){
_url = m.Value;
_url = _url.Replace("<url>","");
_url = _url.Replace("</url>","");
_urlAry += _url + "|";
} else {
_desc = m.Value;
_desc = _desc.Replace("<title>","");
_desc = _desc.Replace("</title>","");
_descAry += _desc + "|";
}
}
_descAry = _descAry.Substring(0,_descAry.Length-1);
_urlAry = _urlAry.Substring(0,_urlAry.Length-1);
Response.Write("theUrls="+Server.UrlEncode(_urlAry)
+"&theTitles="+Server.UrlEncode(_descAry));
}
</script>
====================================================
Now let's take a look at what is happening on the Flash side:
The Flash part of this application is done entirely in ActionScript.
That includes the display, text styles and backgrounds. You can view the ActionScript
here without the comments.
Here we set the global styles for text formatting. No font sizes are being set here.
Font sizes will be set on each text box. That way, the other style attributes
can be reused.
function set_gStyles(){
tStyle = new TextFormat();
tStyle.font = "verdana";
tStyle.color = parseInt("ffffff",16);
tStyle.leftMargin = 5;
}
This function creates a textfield to relay the status of communicating
with the server. The text size is set to 10 and uses the global text styles.
function chk_server_conn(){
_root.createTextField("item_text",0,0,(_root["newsitem_text"]._y)+23,300,16);
tStyle.size = 10;
_root["item_text"].selectable = false;
_root["item_text"].text = "Checking Server Connection";
_root["item_text"].setTextFormat(tStyle);
}
This function sets the textfield message to read that a connection could not
be established with the exteranl file.
function showErrMsg(){
tStyle.size = 10;
_root["item_text"].text = "Connection Failed";
_root["item_text"].setTextFormat(tStyle);
}
This function makes the header box that reads "Macromedia News".
First we create an empty movieclip, give it an instance name of "headerbg" and set the
depth to -1. Then the box has a color fill of "#284E75" and a dark gray, half pixel stroke.
The move to function places the starting x and y coordinates for the box on the stage and the lineTo()
function draws the box. The endFill() function closes everthing up. Next, we create a
textfield named header and set it's attributes.
function make_header(){
_root.createEmptyMovieClip ("headerbg", -1);
with (_root["headerbg"]){
beginFill (0x284E75);
lineStyle (.5, 0x333333, 100);
moveTo (0, 0);
lineTo (0, 23);
lineTo (450, 23);
lineTo (450, 0);
endFill();
}
_root["headerbg"].createTextField("header",110,0,0,300,16);
_root["headerbg"]["header"].text = "Macromedia News";
_root["headerbg"]["header"].type = "static";
_root["headerbg"]["header"].selectable = false;
_root["headerbg"]["header"].autoSize = "left";
tStyle.size = 14;
_root["headerbg"]["header"].setTextFormat(tStyle);
}
The same principals as above but used to make the box that
will contain the news item_text.
function make_newsitem(){
_root.createEmptyMovieClip ("news_item", -20);
with (_root["news_item"]){
moveTo (0, 10);
beginFill (0x336699);
moveTo (0, 23);
lineTo (0, 40);
lineTo (450, 40);
lineTo (450, 23);
endFill();
}
}
This is the function that duplicates the "news_item" clip for
each news item. The variables being passed in from the getNews() function
are: tAry = myTitleAry and uAry = myUrlAry. These arrays come from
the get_news() function. The for()loop loops thru the length of the url array
and duplicates the "news_item" clip and gives each a new instance name and
depth. Then the y position is set for the new clip using the position of the
original clip and the height of the "news_item" clip multiplied by the number of
clip produces so far (i). Next, create a new textfield instance that sits on top
of the new "news_item" clip. Set the y position of the textfield equal to that of
the new "news_item" clip. The "theUrl" variable is equal to the current index value
of the uAry array and the "item_index" variable is equal to the current value of i.
Now we can set attributes for the current instance of the textfield. Autosizing will
extend the textfield to be atleast as long as the text held within. Set the textfield
text value equal to the current index value of the tAry array. Last, we set the global
text size and set the global text styles. You may be wondering why i have two
incrementing variables in my loop (i and j). i is used for getting the array indexes,
clip depths and keeping count in the loop. The variable "j" only has one function - to
start the textfield depth above the movieclips. since "i" starts at zero, the first
textfield's properties would not be accessable since anything multiplied by 0 is still
just 0 and to make sure that there was no conflict with clip depths, we multiply j * 10.
function makeList(tAry,uAry){
for (var i=0,j=1;i<uAry.length;i++,j++){
duplicateMovieClip(_root["news_item"],"news_item"+i,i);
_root["news_item"+i]._y =
(_root["news_item"]._y +
((_root["news_item"]._height-1) * i));
_root.createTextField
("item_text"+i,j*10,0,(_root["news_item"+i]._y)+24,300,14);
this["news_item"+i].theUrl=uAry[i];
this["news_item"+i].item_index = i;
this["item_text"+i].selectable = false;
this["item_text"+i].autoSize = "left";
this["item_text"+i].text=tAry[i];
tStyle.size = 10;
this["item_text"+i].setTextFormat(tStyle);
These functions handle the movieclip instance events. "myBg" sets the news_item instance
background color using the color object when it is rolled over. Another instance of the
color object is used to change the font color when it is rolled over. To get the path to
the "item_text" instance that we want to reference, the variable "item_index" is concatenated
to the instance name - _root["item_text"].
this["news_item"+i].onRollOver = function(myColor){
var myBg = new Color(this);
myBg.setRGB(parseInt("aaaaaa",16));
var myFontColor = new Color(_root["item_text"+this.item_index]);
myFontColor.setRGB(parseInt("333333",16));
}
These functions do the same as above but change the colors back
when the mouse rolls off the "news_item" movieclip.
this["news_item"+i].onRollOut = function(){
var myBg = new Color(this);
myBg.setRGB(parseInt("336699",16));
var myFontColor = new Color(_root["item_text"+this.item_index]);
myFontColor.setRGB(parseInt("ffffff",16));
}
this["news_item"+i].onRelease = function(){
getURL(this.theUrl,"_blank");
}
}
}
Here is the function that gets the variables/values from getNews.aspx.
"ret"(short for return) is the new instance of LoadVars(). If the function gets
a return value from the server (success), then use the split() function on the
values and index them into two arrays (myUrlAry and myTitleAry). These values are
then used in the makeList() function. If the function does not receive a return
value then call the showErrMsg() function.
function get_news(){
ret = new LoadVars();
ret.onLoad = function(success){
if(success){
ret.myUrlAry = ret.theUrls.split('|');
ret.myTitleAry = ret.theTitles.split('|');
makeList(ret.myTitleAry,ret.myUrlAry);
} else {
showErrMsg();
}
}
// load the values from "getNews.aspx"
ret.load("getNews.txt");
}
Here is the function that loads the other primary functions
function init(){
set_gStyles();
chk_server_conn();
make_newsitem();
make_header();
get_news();
}
call the function above
init();
That's it!! Good Luck!!