Wednesday, October 5, 2011

How To: SharePoint 2010 News Scroller Web Part

In this tutorial I will show you how to create a dynamic news scroller that will take the top news headlines and make them scroll upwards after a short period of time. This was done with a SharePoint 2010 Visual Web Part and some JavaScript from DynamicDrive.com.


For the purpose of this tutorial I will be hard-coding a URL from News24.com and using their latest articles. If you want the web part to be more dynamic in letting users choose their region or a different news site you can look at adding custom properties for the web part which can be set later on. View my How To: SharePoint 2010 Weather Web Part blog article to find out more on how this is done.

1. Create a new Visual Web Part project

Click on File > New > Project and select the Visual Web Part project template from the SharePoint 2010 Templates and click Ok.
Deploying as a Farm solution should be your only option so just click on Finish.
(I have renamed my web part to NewsScrollerWebPart for this tutorial)


2. Add the JavaScript for the scroller

Right click your project and click Add > SharePoint Mapped Folder and choose the TEMPLATES/LAYOUTS folder. Add a new normal folder inside with the name of your web part e.g. NewsScrollerWebPart. Create a new JScript file inside and paste the following code into it:





/***********************************************
* Pausing up-down scroller- © Dynamic Drive (
www.dynamicdrive.com)
* Visit
http://www.dynamicdrive.com/ for this script and 100s more.
***********************************************/

function pausescroller(content, divId, delay) {
    this.content = content //message array content
    this.tickerid = divId //ID of ticker div to display information
    this.delay = delay //Delay between msg change, in miliseconds.
    this.mouseoverBol = 0 //Boolean to indicate whether mouse is currently over scroller (and pause it if it is)
    this.hiddendivpointer = 1 //index of message array for hidden div
    document.write('<div id="' + divId + '" style="position: relative; overflow: hidden"><div class="innerDiv" style="position: absolute; width: 100%" id="' + divId + '1">' + content[0] + '</div><div class="innerDiv" style="position: absolute; width: 100%; visibility: hidden" id="' + divId + '2">' + content[1] + '</div></div>')
    var scrollerinstance = this
    if (window.addEventListener) //run onload in DOM2 browsers
        window.addEventListener("load", function () { scrollerinstance.initialize() }, false)
    else if (window.attachEvent) //run onload in IE5.5+
        window.attachEvent("onload", function () { scrollerinstance.initialize() })
    else if (document.getElementById) //if legacy DOM browsers, just start scroller after 0.5 sec
        setTimeout(function () { scrollerinstance.initialize() }, 500)
}

// -------------------------------------------------------------------
// initialize()- Initialize scroller method.
// -Get div objects, set initial positions, start up down animation
// -------------------------------------------------------------------

pausescroller.prototype.initialize = function () {
    this.tickerdiv = document.getElementById(this.tickerid)
    this.visiblediv = document.getElementById(this.tickerid + "1")
    this.hiddendiv = document.getElementById(this.tickerid + "2")
    this.visibledivtop = parseInt(pausescroller.getCSSpadding(this.tickerdiv))
    //set width of inner DIVs to outer DIV's width minus padding (padding assumed to be top padding x 2)
    this.visiblediv.style.width = this.hiddendiv.style.width = this.tickerdiv.offsetWidth - (this.visibledivtop * 2) + "px"
    this.getinline(this.visiblediv, this.hiddendiv)
    this.hiddendiv.style.visibility = "visible"
    var scrollerinstance = this
    document.getElementById(this.tickerid).onmouseover = function () { scrollerinstance.mouseoverBol = 1 }
    document.getElementById(this.tickerid).onmouseout = function () { scrollerinstance.mouseoverBol = 0 }
    if (window.attachEvent) //Clean up loose references in IE
        window.attachEvent("onunload", function () { scrollerinstance.tickerdiv.onmouseover = scrollerinstance.tickerdiv.onmouseout = null })
    setTimeout(function () { scrollerinstance.animateup() }, this.delay)
}


// -------------------------------------------------------------------
// animateup()- Move the two inner divs of the scroller up and in sync
// -------------------------------------------------------------------

pausescroller.prototype.animateup = function () {
    var scrollerinstance = this
    if (parseInt(this.hiddendiv.style.top) > (this.visibledivtop + 5)) {
        this.visiblediv.style.top = parseInt(this.visiblediv.style.top) - 5 + "px"
        this.hiddendiv.style.top = parseInt(this.hiddendiv.style.top) - 5 + "px"
        setTimeout(function () { scrollerinstance.animateup() }, 50)
    }
    else {
        this.getinline(this.hiddendiv, this.visiblediv)
        this.swapdivs()
        setTimeout(function () { scrollerinstance.setmessage() }, this.delay)
    }
}

// -------------------------------------------------------------------
// swapdivs()- Swap between which is the visible and which is the hidden div
// -------------------------------------------------------------------

pausescroller.prototype.swapdivs = function () {
    var tempcontainer = this.visiblediv
    this.visiblediv = this.hiddendiv
    this.hiddendiv = tempcontainer
}

pausescroller.prototype.getinline = function (div1, div2) {
    div1.style.top = this.visibledivtop + "px"
    div2.style.top = Math.max(div1.parentNode.offsetHeight, div1.offsetHeight) + "px"
}

// -------------------------------------------------------------------
// setmessage()- Populate the hidden div with the next message before it's visible
// -------------------------------------------------------------------

pausescroller.prototype.setmessage = function () {
    var scrollerinstance = this
    if (this.mouseoverBol == 1) //if mouse is currently over scoller, do nothing (pause it)
        setTimeout(function () { scrollerinstance.setmessage() }, 100)
    else {
        var i = this.hiddendivpointer
        var ceiling = this.content.length
        this.hiddendivpointer = (i + 1 > ceiling - 1) ? 0 : i + 1
        this.hiddendiv.innerHTML = this.content[this.hiddendivpointer]
        this.animateup()
    }
}

pausescroller.getCSSpadding = function (tickerobj) { //get CSS padding value, if any
    if (tickerobj.currentStyle)
        return tickerobj.currentStyle["paddingTop"]
    else if (window.getComputedStyle) //if DOM2
        return window.getComputedStyle(tickerobj, "").getPropertyValue("padding-top")
    else
        return 0
}


3. Create the JavaScript Links from the RSS XML

The script file uses a javascript array of links to render. We will basically just pull out the XML from the RSS feed, select the title and link nodes for each news headline and build up html links for the array:


public partial class NewsScrollerUserControl : UserControl
{
 // url of the RSS feed
 public const string _rssUrl = "
http://feeds.news24.com/articles/News24/TopStories/rss";
 protected void Page_Load(object sender, EventArgs e)
 {
  XmlDocument xdoc = CreateXmlDoc();
  XmlNodeList nodeList = xdoc.SelectNodes("/rss/channel/item");
  string script = BuildScript(nodeList);

  // register the script on the page
  ClientScriptManager csm = Page.ClientScript;
  csm.RegisterClientScriptBlock(this.GetType(), "ScrollerScript", script, true);
 }

 private String BuildScript(XmlNodeList nodeList)
 {
  // build the script
  StringBuilder sb = new StringBuilder();
  sb.Append("var pausecontent = new Array();");

  // add a link for each news headline
  int count = 0;
  foreach (XmlNode node in nodeList)
  {
   sb.Append(String.Format("pausecontent[{0}] = '<a target=\"_blank\" href=\"{1}\">{2}</a>'; ", count, node.SelectSingleNode("link").InnerText, node.SelectSingleNode("title").InnerText));
   count++;
  }

  return sb.ToString();
 }

 private XmlDocument CreateXmlDoc()
 {
  // create a reader and populate the document
  XmlReader reader = XmlReader.Create(_rssUrl);
  XmlDocument doc = new XmlDocument();
  doc.Load(reader);
  return doc;
 }
}


4. Add the Styles, JavaScript call method and script reference
This call method will make a call with your rendered links to the JavaScript file and bring back the scrolling HTML.

<script src="/_layouts/NewsScrollerWebPart/Scroller.js" type="text/javascript"></script>
<style type="text/css">
    #pscroller{
        width: 100%;
        height: 15px;
        border: 1px solid #ededed;
        padding: 3px;
        font-family:Verdana, Arial, sans-serif;
        font-size:8pt;
    }

    #pscroller a{
        text-decoration: none;
        color:#676767;
    }
   
    #pscroller a:hover{
        text-decoration: underline;
        color:#676767;
    }
</style>

<script type="text/javascript">
    new pausescroller(pausecontent, "pscroller", 3500);
</script>

3 comments:

  1. can i have a downlodable version of the solution?

    ReplyDelete
  2. Could I also have the downloadable version please? siva.naidoo@nkomati.co.za

    ReplyDelete
  3. Hi, unfortunately I don't have a downloadable version of the solution.

    ReplyDelete