/**
 * News and time handling. This object handles the Ajax request to the server,
 * grabs the server time from the HTTP response header, the news feed from
 * the content and other internal information from comments in the content.
 * This is the main object. After each refresh, the time object and the news
 * ticker are updated.
 *
 * @version $Revision: 1.2 $
 *
 * (C) Copyright 2010 Feuerstein and Associates.
 */

// Singleton instance.

var qdbNews = null;

// Running in IE?

var isIE = false;

var formatModels = new Array(4);

formatModels[1] = 'D';
formatModels[2] = 'M';
formatModels[3] = 'Q';

/**
 * Constructor.
 * @param   showQuizTime
 *                  Optionally controls whether the news ticker should start in
 *                  non-animated mode, showing the quiz time news item.
 * @param   countDownRedirect
 *                  Optional url to redirect to when quiz starts.
 */

function QdbNews(showQuizTime, countDownRedirect) {
  this.request = null;
  this.serverTime = null;
  this.newsXml = null;
  this.quizTaken = null;
  this.topicList = null;
  this.linkList = null;
  this.apexInfo = null;

  this.quizTypeId = null;
  this.quizStarts = null;
  this.quizEnds = null;
  this.quizPeriod = null;

  this.qdbTime = new QdbTime();
  this.qdbNewsTicker = new QdbNewsTicker();

  if (showQuizTime)
    this.showQuizTime = true;
  else this.showQuizTime = false;

  if (countDownRedirect && countDownRedirect.length > 0)
    this.countDownRedirect = countDownRedirect;
  else this.countDownRedirect = null;

  this.refresh = QdbNewsRefresh;
  this.callback = QdbNewsCallback;
  this.buildLists = QdbNewsBuildLists;
  this.getElementText = QdbNewsGetElementText;
  this.getTopicList = QdbNewsGetTopicList;
  this.getLinkList = QdbNewsGetLinkList;
  this.toString = QdbNewsToString;

  qdbNews = this;
}

/**
 * This function is called any time we need to refresh server time and current
 * news. Calls the stored procedure QDB_RSS_FEED.
 * @param   apexInfo
 *                  Various APEX-related info -- application ID, page number and
 *                  session ID, separated by :.
 */

function QdbNewsRefresh(apexInfo) {
  if (apexInfo)
    // New APEX info, overwrite on this and use this going forward.
    this.apexInfo = apexInfo;

  // Instantiate an XMLHttpRequest object.
  if (window.XMLHttpRequest) {
    // Non-IE.
    this.request = new XMLHttpRequest();
  }
  else {
    // IE.
    isIE = true;
    this.request = new ActiveXObject("Microsoft.XMLHTTP");
  }

  this.request.onreadystatechange =
    function () {
      if (qdbNews.request.readyState == 4) {
        if (qdbNews.request.status == 200)
          qdbNews.callback();
        else {
          // Something went wrong. Try again in 1 min.
          this.request = null;
          setTimeout("qdbNews.refresh()", 60000);
        }
      }
    };

  var prefixPath =
      window.location.pathname.substring(0, window.location.pathname.length - 1);
  var schemaName = this.apexInfo.substring(this.apexInfo.lastIndexOf(":") + 1);

  url = prefixPath +
      "f?p=" + this.apexInfo +
      ":APPLICATION_PROCESS=QDB_RSS_FEED:::QDB_RSS_FEED_DUMMY:" +
      new Date().getTime();

  this.request.open("GET", url, true);
  this.request.setRequestHeader('User-Agent', 'XMLHTTP/1.0');
  this.request.setRequestHeader('Cache-Control', 'no-cache');
  this.request.send(null);
}

/**
 * This is the function that will repeatedly be called by our XMLHttpRequest
 * object during the lifecycle of the request.
 */

function QdbNewsCallback() {
  this.serverTime = this.request.getResponseHeader("QDB-Date");
  if (this.serverTime == null || this.serverTime.length == 0)
    this.serverTime = this.request.getResponseHeader("Date");

  if (this.serverTime == null || this.serverTime.length == 0) {
    // HTTP server didn't send Date HTTP response header. Grab it from the
    // comment in the XML instead.
    i = this.request.responseText.indexOf("<!-- Date: ");
    if (i > 0)
      this.serverTime = this.request.responseText.substring(i + 11, i + 11 + 29);
  }

  // Quiz type.
  this.quizTypeId = parseInt(this.request.getResponseHeader("QDB-Quiz-Type"));
  // Quiz starts on.
  this.quizStarts = this.request.getResponseHeader("QDB-Quiz-Starts");
  // Quiz ends on.
  this.quizEnds = this.request.getResponseHeader("QDB-Quiz-Ends");
  // Quiz period.
  this.quizPeriod = this.request.getResponseHeader("QDB-Quiz-Period");

  // Has the user already taken today's quiz?
  this.quizTaken = this.request.getResponseHeader("QDB-Quiz-Taken");
  if (this.quizTaken == null || this.quizTaken.length == 0) {
    i = this.request.responseText.indexOf("<!-- Quiz-taken: ");
    if (i > 0)
      this.quizTaken = this.request.responseText.substring(i + 17, i + 17 + 5);
  }
  if (this.quizTaken && this.quizTaken.length > 0)
    this.quizTaken = this.quizTaken.replace(/^\s+|\s+$/g, "");

  this.newsXml = this.request.responseXml;
  if (! this.newsXml) {
    // responseXml for some reason didn't parse. Parse it from responseText.
    if (window.DOMParser)
      this.newsXml = new DOMParser().parseFromString(this.request.responseText, "text/xml");
    else {
      // Internet Explorer
      this.newsXml = new ActiveXObject("Microsoft.XMLDOM");
      this.newsXml.async = "false";
      this.newsXml.loadXML(this.request.responseText);
    }
  }

  this.request = null;

  this.buildLists();

  // Refresh time and ticker.
  this.qdbTime.refresh();
  this.qdbNewsTicker.refresh();
  this.qdbNewsTicker.init(this.showQuizTime);

  // Prepare for taking the playoff quiz.
  if (this.countDownRedirect) {
    var diff = new Date(this.quizStarts) - new Date(this.serverTime.replace("GMT", "UTC"));

    if (diff > 0)
      setTimeout("redirect('" + this.countDownRedirect + "')", diff);
    else redirect(this.countDownRedirect);
  }
}

/**
 * Builds topic and link lists through the RSS news feed.
 */

function QdbNewsBuildLists() {
  this.topicList = new Array();
  this.linkList = new Array();

  var items = this.newsXml.getElementsByTagName("item");

  // Loop through <item> elements, and add each nested <title> element to topic
  // list, each <link> element to link list.
  for (var i = 0; i < items.length; i++) {
    this.topicList.push(this.getElementText("", "title", items[i], 0));
    this.linkList.push(this.getElementText("", "link", items[i], 0));
  }
}

/**
 * Retrieve text of an XML document element, including elements using
 * namespaces.
 * @param   prefix  Namespace.
 * @param   local   Element name.
 * @param   parentElem
 *                  Parent element name.
 * @param   index   Index, starting from 0.
 * @return  Element value.
 */

function QdbNewsGetElementText(prefix, local, parentElem, index) {
  var result = "";

  if (prefix && isIE)
    // IE way of handling namespaces.
    result = parentElem.getElementsByTagName(prefix + ":" + local)[index];
  else {
    /*
     * The namespace versions of this method operate differently in Safari and
     * Mozilla, but both return value with just local name, provided there
     * aren't conflicts with non-namespace element names.
     */
    result = parentElem.getElementsByTagName(local)[index];
  }
  if (result) {
    /*
     * Get text, accounting for possible whitespace (carriage return) text
     * nodes.
     */
    if (result.childNodes.length > 1)
      return result.childNodes[1].nodeValue;
    else return result.firstChild.nodeValue;
  }
  else return "n/a";
}

/**
 * Gets topic list.
 * @return  Topic list.
 */

function QdbNewsGetTopicList() {
  return this.topicList;
}

/**
 * Gets link list.
 * @return  Link list.
 */

function QdbNewsGetLinkList() {
  return this.linkList;
}

/**
 * Converts to textual representation.
 */

function QdbNewsToString() {
  return
      "PLSCNews = {" +
        "serverTime = " + this.serverTime + ", "
        "newsXml = " + this.newsXml +
      "}";
}

/**
 * Server time handling through an initial time and subsequent ticks every 60
 * seconds. Once an hour (and if we have just woken up from
 * sleep/suspend/hibernate) the clock is synchronized with the server, such that
 * we obtain the latest news.
 *
 * (C) Copyright 2010 Feuerstein and Associates.
 */

// Singleton instance.

var qdbTime = null;

// Month names.

var months = new Array(12);

months[0]  = "January";
months[1]  = "February";
months[2]  = "March";
months[3]  = "April";
months[4]  = "May";
months[5]  = "June";
months[6]  = "July";
months[7]  = "August";
months[8]  = "September";
months[9]  = "October";
months[10] = "November";
months[11] = "December";

// Weekday names.

var weekDays = new Array(8);

weekDays[1] = "Mon";
weekDays[2] = "Tue";
weekDays[3] = "Wed";
weekDays[4] = "Thu";
weekDays[5] = "Fri";
weekDays[6] = "Sat";
weekDays[7] = "Sun";

/**
 * Constructor.
 */

function QdbTime() {
  this.time = null;
  this.correctedTime = null;
  this.lastTime = 0;
  this.thisTime = 0;
  this.timeOffset = 0;
  this.interval = 0;

  this.dom = document.getElementById;
  this.ie4 = document.all;

  this.init = QdbTimeInit;
  this.refresh = QdbTimeRefresh;
  this.tick = QdbTimeTick;
  this.show = QdbTimeShow;

  this.getDate = QdbTimeGetDate;
  this.formatDate = QdbTimeFormatDate;
  this.formatTime = QdbTimeFormatTime;
  this.getTimeDiff = QdbTimeGetTimeDiff;

  this.getObjectById = QdbTimeGetObjectById;

  qdbTime = this;
}

/**
 * Initializer. To be called after constructor.
 */

function QdbTimeInit() {
  this.refresh();
}

/**
 * Refresh the time with the server through a newly obtained response from the
 * server, handled by QdbNews.
 */

function QdbTimeRefresh() {
  this.thisTime = new Date().getTime();

  this.timeOffset = 0;
  this.time = null;
  this.time = new Date(qdbNews.serverTime.replace("GMT", "UTC"));
  if (qdbNews.quizTypeId == 3) {
    this.correctedTime = this.time;
    // Pick a date in previous quarter.
    //this.correctedTime.setUTCSeconds(this.correctedTime.getUTCSeconds() - 30 * 86400);
  }
  else this.correctedTime = this.time;

  this.show();

  var ss;
  if (qdbNews.quizTypeId == 3)
    ss = 1;
  else {
    // Synchronize to the minute the first time, then every 60 seconds.
    ss = 60 - this.time.getUTCSeconds();
  }

  setTimeout("qdbTime.tick(" + ss + ")", ss * 1000);
}

/**
 * This method is called once per minute (and at startup such that we tick on
 * the minute). If it is detected that it's more than 90 seconds since we were
 * called last, we refresh with the server as this indicates that we've just
 * woken up from sleep/hibernation/suspension or something else is wrong. We
 * also refresh each hour in order to get new news.
 * @param   t       Number of seconds we must add. Usually 60 but initially it's
 *                  usually less in order to synchronize by when the minutes
 *                  change.
 */

function QdbTimeTick(t) {
  this.thisTime = null;
  this.thisTime = new Date().getTime();
  this.timeOffset += t;

  this.time.setUTCSeconds(this.time.getUTCSeconds() + t);
  if (this.timeOffset >= 3600 ||
      (this.thisTime - this.lastTime) > 90000 && this.lastTime > 0) {
    // An hour has passed or just woken up from hibernation/sleep/suspension.
    // Refresh with server.
    clearInterval(this.interval);
    this.interval = 0;

    if ((this.thisTime - this.lastTime) > 90000 && this.lastTime > 0) {
      // Woken up. Clear the quiz time as it's unknown at this point.
      this.thisTime = this.thisTime;
      this.lastTime = this.thisTime;

      if (qdbNewsTicker)
        qdbNewsTicker.updateTime(true);
    }

    qdbNews.refresh();

    return;
  }
  if (this.interval == 0) {
    var delta;

    if (qdbNews.quizTypeId == 3)
      delta = 1;
    else delta = 60;

    this.interval = setInterval("qdbTime.tick(" + delta + ")", delta * 1000);
  }

  this.lastTime = null;
  this.lastTime = this.thisTime;

  this.show();
}

/**
 * Show time.
 */

function QdbTimeShow() {
  qdbNews.qdbNewsTicker.updateTime(false);
}

/**
 * Get current date, formatted.
 * @param   formatModel
 *                  Format model: 'D', 'W', 'M', 'Q'. If not supplied, this is
 *                  calculated based on quiz type ID.
 * @return  Date formatted.
 */

function QdbTimeGetDate(formatModel) {
  return this.formatDate(
    this.correctedTime,
    formatModel == null ? formatModels[qdbNews.quizTypeId] : formatModel
  );
}

/**
 * Formats date part of given date.
 * @param   d       Date.
 * @param   formatModel
 *                  Format model: 'D', 'W', 'M', 'Q'.
 * @return  Date formatted (date part).
 */

function QdbTimeFormatDate(d, formatModel) {
  switch (formatModel) {
    case 'D':
      return weekDays[d.getUTCDay() == 0 ? 7 : d.getUTCDay()] + " " +
          d.getUTCDate() + " " + months[d.getUTCMonth()] + " " + d.getUTCFullYear();
    case 'W':
      return 'Week not supported yet';
    case 'M':
      return months[d.getUTCMonth()] + " " + d.getUTCFullYear();
    case 'Q':
      return 'Q' + (1 + floor(d.getUTCMonth() / 3)) + " " + d.getUTCFullYear();
  }
}

/**
 * Formats time part of given date.
 * @param   d       Date.
 * @return  Date formatted (time part).
 */

function QdbTimeFormatTime(d) {
  var hh = d.getUTCHours();
  if (hh < 10)
    hh = "0" + hh;

  var mi = d.getUTCMinutes();
  if (mi < 10)
    mi = "0" + mi;

  var ss = d.getUTCSeconds();
  if (ss < 10)
    ss = "0" + ss;

  return hh + ":" + mi + ":" + ss;
}

/**
 * Returns textual diff between two dates with time parts, assuming that d2 >
 * d1.
 * @param   d1      Date 1.
 * @param   d2      Date 2.
 * @return  Date/time diff.
 */

function QdbTimeGetTimeDiff(d1, d2) {
  var years = 0;
  var months = 0;
  var days = 0;
  var hours = 0;
  var minutes = 0;
  var seconds = 0;

  var result = "";

//result += "d1 = " + d1 + ", d2 = " + d2 + ". ";
  var diff = d2.getTime() - d1.getTime();
//result += "diff = " + diff + ". ";

  days = Math.floor(diff / 1000 / 60 / 60 / 24);
  diff -= days * 1000 * 60 * 60 * 24;

  hours = Math.floor(diff / 1000 / 60 / 60);
  diff -= hours * 1000 * 60 * 60;

  minutes = Math.floor(diff / 1000 / 60);
  diff -= minutes * 1000 * 60;

  if (qdbNews.quizTypeId == 3) {
    seconds = Math.floor(diff / 1000);
    diff -= seconds * 1000;
  }
  else seconds = 0;

  if (days >= 1)
    result += days + " day" + (days == 1 ? "" : "s");
  if (hours >= 1) {
    if (result.length > 0) {
      if (minutes > 0)
        result += ", ";
      else result += " and ";
    }
    result += hours + " hour" + (hours == 1 ? "" : "s");
  }
  if (minutes >= 1) {
    if (result.length > 0) {
      if (seconds > 0)
        result += ", ";
      else result += " and ";
    }
    result += minutes + " minute" + (minutes == 1 ? "" : "s");
  }
  if (qdbNews.quizTypeId == 3) {
    // Also seconds.
    if (seconds >= 1) {
      if (result.length > 0)
        result += " and ";
      result += seconds + " second" + (seconds == 1 ? "" : "s");
    }
  }

  return result;
}

/**
 * Get DOM object through ID.
 * @param   id      ID of object.
 * @return  Object reference if found, false otherwise.
 */

function QdbTimeGetObjectById(id) {
  if (this.dom)
    return document.getElementById(id);
  else if (this.ie4)
    return document.all[id];
  else return false;
}

/**
 * News ticker handling. The news items are obtained from the server through
 * QdbNews. A special "news item" is the quiz time, either showing time left
 * (on weekdays when the user is unknown or hasn't played), time when the quiz
 * was taken (on weekdays if the user is known and has played) or time until
 * next quiz (on weekends).
 *
 * (C) Copyright 2010 Feuerstein and Associates.
 */

// Singleton instance.

var qdbNewsTicker = null;

// Running in IE?

var isIe = document.all && ! window.opera && window.XMLHttpRequest;

/**
 * Constructor.
 */

function QdbNewsTicker() {
  this.time = null;
  this.news = null;
  this.minutesSinceRefresh = 0;
  this.playing = true;

  this.dom = document.getElementById;
  this.ie4 = document.all;

  this.topicList = new Array();
  this.linkList = new Array();

  // Current news item.
  this.cnt = 0;
  // current string.
  this.curr = "";
  // Current position being animcated.
  this.i = -1;
  this.w = 0;
  this.tI = 0;
  this.tT = 0;
  this.tickCount = 0;

  this.init = QdbNewsTickerInit;
  this.refresh = QdbNewsTickerRefresh;
  this.tick = QdbNewsTickerTick;
  this.animate = QdbNewsTickerAnimate;
  this.currentHasLink = QdbNewsTickerCurrentHasLink;

  this.next = QdbNewsTickerNext;
  this.prev = QdbNewsTickerPrev
  this.play = QdbNewsTickerPlay;
  //this.pause = QdbNewsTickerPause;
  this.stop = QdbNewsTickerStop;
  this.onClick = QdbNewsTickerOnClick;

  this.navigate = QdbNewsTickerNavigate;
  this.quizTime = QdbNewsTickerQuizTime;

  this.increment = QdbNewsTickerIncrement;
  this.decrement = QdbNewsTickerDecrement;
  this.onMouseOver = QdbNewsTickerOnMouseOver;
  this.onMouseOut = QdbNewsTickerOnMouseOut;

  this.updateTime = QdbNewsTickerUpdateTime;
  this.getNewsObject = QdbNewsTickerGetNewsObject;

  this.getObjectById = QdbNewsTickerGetObjectById;

  qdbNewsTicker = this;
}

/**
 * Initializer.
 * @param   showQuizTime
 *                  Optionally controls whether the news ticker should start in
 *                  non-animated mode, showing the quiz time news item.
 */

function QdbNewsTickerInit(showQuizTime) {
  qdbNewsTicker.newsObject = qdbNewsTicker.getNewsObject();
  qdbNewsTicker.stop();
  if (showQuizTime)
    qdbNewsTicker.quizTime();
  else {
    if (qdbNewsTicker.playing)
      qdbNewsTicker.tI = setInterval('QdbNewsTickerTick()', 60);
  }
}

/**
 * Refresh after a new response from server.
 */

function QdbNewsTickerRefresh() {
  this.time = qdbTime.time;
  this.topicList = qdbNews.getTopicList();
  this.linkList = qdbNews.getLinkList();
  for (var i = 0; i < this.topicList.length; i++)
    this.topicList[i] = "News: " + this.topicList[i];
  this.topicList.push("");
  this.linkList.push("");
  this.updateTime(false);
}

/**
 * Update the quiz time "news item". Takes into consideration whether it's a
 * weekday or weekend and whether the user has played or not.
 */

function QdbNewsTickerUpdateTime(unknown) {
  var quizNews = "Quiz: ";

  if (unknown)
    quizNews += "Server date and time unknown";
  else {
    var days = 0;
    var hours = 0;
    var minutes = 0;
    var dayOfWeek = -1;

    this.time = qdbTime.time;
    dayOfWeek = this.time.getUTCDay();
    if (dayOfWeek == 0)
      dayOfWeek = 7;

    var quizTaken = qdbNews.quizTaken != "false" &&
        qdbNews.quizTaken != null && qdbNews.quizTaken != "null";
    var endsOn = null;
    var startsOn = null;
    var quizPeriod = qdbNews.quizPeriod;

    switch (qdbNews.quizTypeId) {
      case 1:
        // Daily quiz.
        if (dayOfWeek <= 5) {
          // Time left to play if not taken.
          days = 0;
          if (! quizTaken)
            endsOn = new Date(qdbNews.quizEnds);
        }
        if (dayOfWeek >= 6) {
          // Time left for next start.
          startsOn = new Date(this.time);

          startsOn.setUTCDate(startsOn.getUTCDate() + (8 - dayOfWeek));
          startsOn.setUTCHours(0);
          startsOn.setUTCMinutes(0);
          startsOn.setUTCSeconds(0);
          startsOn.setUTCMilliseconds(0);
          quizNews += "No quiz on weekends. ";
        }
        break;
      case 2:
        // ToadWorld quiz. Fall through to playoff.
      case 3:
        // Playoff quiz.
        if (! quizTaken) {
          if (qdbNews.quizEnds)
            endsOn = new Date(qdbNews.quizEnds);
          if (qdbNews.quizStarts)
            startsOn = new Date(qdbNews.quizStarts);
        }
    }

    if (! quizTaken) {
      if (endsOn) {
        quizNews +=
            qdbNews.qdbTime.getTimeDiff(qdbTime.time, endsOn) +
            " left to play the quiz of " + quizPeriod /* qdbNews.qdbTime.getDate()*/;
      }
      if (startsOn) {
        quizNews +=
            "Next quiz for " +
            quizPeriod /*QdbTimeFormatDate(startsOn, 'D')*/ +
            " starts in " +
            qdbNews.qdbTime.getTimeDiff(qdbTime.time, startsOn);
      }
    }
    else quizNews += "Quiz taken at " + qdbNews.quizTaken;
  }

  this.topicList[this.topicList.length - 1] = quizNews;
  if (! this.playing) {
    /*
     * Ticker is not running so change to quiz time topic and update time
     * directly.
     */
    this.cnt = this.topicList.length - 1;
    this.getNewsObject().innerHTML = quizNews;
  }
}

/**
 * The ticker that ticks every 60ms or so.
 */

function QdbNewsTickerTick() {
  this.tickCount++;
  if (! qdbNewsTicker.animate()) {
    qdbNewsTicker.increment();
    qdbNewsTicker.stop();
    qdbNewsTicker.tT = setTimeout('QdbNewsTickerInit()', 3000);
  }
}

/**
 * Animate the next character in the current news item. If last, pause for 3
 * seconds.
 */

function QdbNewsTickerAnimate() {
  if (this.topicList &&
      this.topicList.length &&
      this.topicList.length > 0 &&
      this.cnt >= 0 &&
      this.cnt < this.topicList.length &&
      this.i < this.topicList[this.cnt].length - 1) {
    this.i++;

    temp1 = this.topicList[this.cnt];
    temp1 = temp1.split('');

    this.curr += temp1[this.i];
    if (this.i < this.topicList[this.cnt].length - 1)
       this.newsObject.innerHTML = this.curr + "_";
    else this.newsObject.innerHTML = this.curr;
    temp1 = null;

/*
    this.newsObject.innerHTML = this.topicList[this.cnt].substring(0, this.i + 1);
    if (this.i < this.topicList[this.cnt].length - 1)
      this.newsObject.innerHTML += "_";
 */

    return true;
  }

  return false;
}

/**
 * Move to next news item (internal).
 */

function QdbNewsTickerIncrement() {
  this.i = -1;
  this.curr = "";
  if (this.cnt < this.topicList.length - 1)
    this.cnt++;
  else this.cnt = 0;
}

/**
 * Move to previous news item (internal).
 */

function QdbNewsTickerDecrement() {
  this.i = -1;
  this.curr = "";
  if (this.cnt > 0)
    this.cnt--;
  else this.cnt = this.topicList.length - 1;
}

/**
 * OnClick. Navigate to the link if the current news item has a link.
 */

function QdbNewsTickerOnClick() {
  var me = QdbNewsTickerGetThis();

  if (me && me.currentHasLink()) {
    me.stop();
    window.location.href = me.linkList[me.cnt];
    //window.location.href.assign(me.linkList[me.cnt]);
  }
}

/**
 * Does the current news item have a link?
 * @param   true or false.
 */

function QdbNewsTickerCurrentHasLink() {
  var cnt = this.cnt;
  var topicList = this.topicList;
  var linkList = this.linkList;

  if (cnt < topicList.length)
    if (/*topicList[cnt].substring(0, 1) == "N" &&*/
          linkList[cnt].length > 0)
      return true;
  return false;
}

/**
 * OnMouseOver. Change the mouse cursor to a hand if the news item has a link.
 */

function QdbNewsTickerOnMouseOver() {
  var me = QdbNewsTickerGetThis();

  if (me) {
    if (me.currentHasLink()) {
      if (isIe)
        me.getNewsObject().style.cursor = 'hand';
      else me.getNewsObject().style.cursor = 'pointer';
    }
    else me.getNewsObject().style.cursor = 'default';
  }
}

/**
 * OnMouseOut. Change the mouse cursor to default.
 */

function QdbNewsTickerOnMouseOut() {
  var me = QdbNewsTickerGetThis();

  if (me)
    me.getNewsObject().style.cursor = 'default';
}

/**
 * Show next news item.
 */

function QdbNewsTickerNext() {
  var tIB = this.tI;

  this.pause();
  // Next item.
  this.increment();
  this.newsObject.innerHTML = this.topicList[this.cnt];
}

/**
 * Show previous news item.
 */

function QdbNewsTickerPrev() {
  var tIB = this.tI;

  this.pause();
  this.decrement();
  this.newsObject.innerHTML = this.topicList[this.cnt];
}

/**
 * Stop animating the ticker.
 

function QdbNewsTickerPause() {
  this.stop();
  this.i = this.topicList[this.cnt].length -1;
  this.newsObject.innerHTML = this.topicList[this.cnt];
  this.getObjectById("PausePlayA").href = "javascript:qdbNews.qdbNewsTicker.play()";
  this.getObjectById("PausePlayImg").src = this.getObjectById("PausePlayImg").src.replace("Pause", "Play");
  this.getObjectById("PausePlayImg").alt = this.getObjectById("PausePlayImg").alt.replace("Stop", "Start");
  this.getObjectById("PausePlayImg").title = this.getObjectById("PausePlayImg").title.replace("Stop", "Start");
  this.playing = false;
}


 * Start animating the ticker.
 */

function QdbNewsTickerPlay() {
  this.playing = true;
  this.stop();
  this.getObjectById("PausePlayA").href = "javascript:qdbNews.qdbNewsTicker.pause()";
  this.getObjectById("PausePlayImg").src = this.getObjectById("PausePlayImg").src.replace("Play", "Pause");
  this.getObjectById("PausePlayImg").alt = this.getObjectById("PausePlayImg").alt.replace("Start", "Stop");
  this.getObjectById("PausePlayImg").title = this.getObjectById("PausePlayImg").title.replace("Start", "Stop");
  this.increment();
  this.init();
}

/**
 * Stop the intervals and timeout, if running.
 */

function QdbNewsTickerStop() {
  if (this.tI != 0) {
    clearInterval(this.tI);
    this.tI = 0;
  }
  if (this.tT != 0) {
    clearTimeout(this.tT);
    this.tT = 0;
  }
}

/**
 * Navigate to News for current news item.
 */

function QdbNewsTickerNavigate() {
  this.onClick();
}

/**
 * Stop animation and show quiz-related news item.
 

function QdbNewsTickerQuizTime() {
  this.pause();
  if (this.topicList.length > 0) {
    this.cnt = this.topicList.length - 1;
    this.getNewsObject().innerHTML = this.topicList[this.cnt];
  }
}


 * Gets the news ticker DIV DOM object.
 * @return  News ticker DIV object.
 */

function QdbNewsTickerGetNewsObject() {
  if (this.newsObject)
    return this.newsObject;
  this.newsObject = qdbNewsTicker.getObjectById('QdbNewsTickerDiv');
  return this.newsObject;
}

/**
 * Get DOM object through ID.
 * @param   id      ID of object.
 * @return  Object reference if found, false otherwise.
 */

function QdbNewsTickerGetObjectById(id) {
  if (this.dom)
    return document.getElementById(id);
  else if (this.ie4)
    return document.all[id];
  else return false;
}

/**
 * Returns the singleton through variable qdbNews.
 * @return  Singleton.
 */

function QdbNewsTickerGetThis() {
  if (qdbNews && qdbNews.qdbNewsTicker)
    return qdbNews.qdbNewsTicker;
  else return undefined;
}

