1:  // composite custom server control class for KUAMStockTicker
   2:   
   3:  using System;
   4:  using System.Web;
   5:  using System.Web.UI;
   6:  using System.Web.UI.WebControls;
   7:  using System.Xml;
   8:  using System.Xml.Xsl;
   9:   
  10:  namespace dgf.utilities.customcontrols
  11:  {
  12:      public class KUAMStockTicker : Control, INamingContainer
  13:      {        
  14:          // private data members
  15:          private string _symbols;
  16:          private string _path;
  17:          private string _color;
  18:          private int _hoursDiff;
  19:          
  20:          // public properties 
  21:          public string StockSymbols
  22:          {
  23:              get { return _symbols; }
  24:              set { _symbols = value; }
  25:          }
  26:          
  27:          public string XSLSource
  28:          {
  29:              get { return this.Context.Server.MapPath(_path); }
  30:              set { _path = value; }
  31:          }
  32:          
  33:          public string BackgroundColor
  34:          {
  35:              get { string userColor = (_color == null || _color == string.Empty) ? "beige" : _color; return userColor; } 
  36:              set { _color = value; } 
  37:          }
  38:          
  39:          public int TimeDiffFromEST
  40:          {
  41:              get { int hours = (_hoursDiff != 0) ? _hoursDiff : 0; return hours; }
  42:              set { _hoursDiff = value; }
  43:          }
  44:          
  45:          // string to query NASDAQ's database
  46:          private string nasdaqSearchString = "http://quotes.nasdaq.com/quote.dll?mode=stock&page=xml";
  47:          
  48:          // private class-level method
  49:          private string GetStockSymbols(string stocks)
  50:          {
  51:              string[] arrSymbols = stocks.Split(new char[] {';'});
  52:              foreach(string stock in arrSymbols)
  53:              {
  54:                  nasdaqSearchString += "&symbol=" + stock;
  55:              }
  56:              return nasdaqSearchString;
  57:          }
  58:          
  59:          // no need to override the base class Render() method, because the rendering is completed within the child controls
  60:          protected override void CreateChildControls()
  61:          {
  62:              // STEP 1: get the query string to use against the NASDAQ data store
  63:              GetStockSymbols(StockSymbols);
  64:              
  65:              // STEP 2: get the XML data from NASDAQ and parse it, formatting it with a custom XSLT stylesheet
  66:              XmlDocument doc = new XmlDocument();
  67:              XslTransform transform = new XslTransform();
  68:              doc.Load(nasdaqSearchString);
  69:              transform.Load(XSLSource);
  70:              Xml xmlStockData = new Xml();
  71:              xmlStockData.Document = doc;
  72:              xmlStockData.Transform = transform;
  73:              
  74:              // STEP 3: write a client-side JavaScript function to reload the control every 20 minutes, and then register this script block to the page framework
  75:              // (the control reloads on its own)
  76:              string code = "<!-- REFRESH THE STOCK TICKER EVERY 20 MINUTES -->\n\t\t";
  77:                  code += "<script language=\"JavaScript\">\n\t\t\t";
  78:                  code += "var intervalID;\n\t\t\t";
  79:                  code += "intervalID = window.setInterval(\"refreshStockTicker()\",1200000);\n\t\t\t";    
  80:                  code += "function refreshStockTicker() {document.execCommand(\"Refresh\");}\n\t\t";
  81:                  code += "</script>\n\t\n\n\n";
  82:              if(!Page.IsClientScriptBlockRegistered("refreshCode"))
  83:              {
  84:                  Page.RegisterClientScriptBlock("refreshCode",code);
  85:              }
  86:              
  87:              // STEP 4: format a Label server control to display a custom time greeting based on the time zone of the client page
  88:              Label lblTimeStamp = new Label();
  89:              DateTime current = DateTime.Now.AddHours(TimeDiffFromEST);
  90:              DateTime startTime = DateTime.Parse("9:00:00 AM").AddHours(TimeDiffFromEST);
  91:              DateTime endTime = DateTime.Parse("4:00:00 PM").AddHours(TimeDiffFromEST);
  92:              
  93:              if(current.DayOfWeek.ToString() != "Saturday" && current.DayOfWeek.ToString() != "Sunday")
  94:              {
  95:                  if((current - startTime).Hours < 0 && (endTime - current).Hours > 0)
  96:                  {
  97:                      lblTimeStamp.Text = "The market is open...data as of " + DateTime.Now.AddHours(TimeDiffFromEST).ToLongTimeString();
  98:                  }
  99:                  else
 100:                  {
 101:                      lblTimeStamp.Text = "The market has closed";
 102:                  }
 103:              }
 104:              else
 105:              {
 106:                  lblTimeStamp.Text = "The market is closed on weekends";
 107:              }
 108:		
 109:              // STEP 5: add the content to the Page object's control tree
 110:              this.Controls.Add(new LiteralControl(code));
 111:              this.Controls.Add(new LiteralControl("<marquee id=\"" + ClientID + "\" onMouseOut=\"" + identifier + ".start();\" onMouseOver=\"" + identifier + ".stop();\" bgcolor=\"" + BackgroundColor + "\" width=\"80%\" scrolldelay=\"2\" scrollamount=\"2\" loop=\"infinite\">"));
 112:              this.Controls.Add(xmlStockData);
 113:              this.Controls.Add(new LiteralControl("</marquee><br/><br/>"));
 114:              this.Controls.Add(lblTimeStamp);
 115:              this.Controls.Add(new LiteralControl("<br/>Data provided courtesy of <a target=\"_blank\" href=\"http://www.nasdaq.com\">NASDAQ</a>"));
 116:          }    
 117:          
 118:          protected void Page_Load(object sender, EventArgs e)
 119:          {
 120:              EnsureChildControls();
 121:          }
 122:      }
 123:  }