CSS3 Running Texts with RSS

In the last article of our workshop about Digital Signage news ticker we learned the first basic technology for horizontal scrolling texts. It is based on CSS3 animations. In this article we will create a real digital signage application by adding informationw from an RSS feed dynamically.

We assume that you already know what is an RSS feed. Otherwise, click on this post which explains feeds and RSS in more detail.

The next Level

css3 running texts with rssIn the last example we created a simple scrolling text for illustration. However, everyday Digital Signage challenges us more than this. If the text comes from an RSS feed, the text length is variable. It is also unknown which horizontal resolution the device has. That’s why we need to be flexible in our design. Furthermore, we now face a problem with the security policy of web browsers. The so-called SOP (Same-Origin-Policy) does not allow to call Javascript or CSS content from another domain than the currently. We will take these hurdles one by one.

A more flexible design concept for CSS3 running texts with RSS

Do you remember css3_animations_2.html? The CSS3 scrolling texts with RSS should now span the entire width of the page. This means that we change the style area to the following:

<style>
	#ticker
	{
		position: relative;
		font: 30px Arial;
		white-space: nowrap;
		animation: moveTicker 10s linear infinite;
		display: inline-block;	
		
	}
	@keyframes moveTicker
	{
		from
		{
			transform: translate3d(0%, 0%, 0px);
			left: 100%;
		}
		to
		{
			transform: translate3d(-100%, 0%, 0px);
			left: 0%;
		}
	}		
</style>

and the body area to:

<body onload="start()">
	<div id="ticker"></div>
</body>

A wrapper div is now unnecessary and has been deleted. Since the ticker-div should get its text from the later Javascript, it stays empty at first. The onload event in the body tag is explained below.
There are some changes in the stylesheet for the ticker. The animation time will be set later depending on the number of headlines and is not relevant here.

As mentioned at the beginning, we do not know which horizontal resolution will be available in future for the display unit. Without the new changes, the ticker div would be set to the width of the browser window. This is usually much smaller than the width of the actual text. This means, that the scrolling text never runs completely because it always jumps back to the starting point in the middle and starts again.

To prevent this from happening, the element is set as an inline block. Thus horizontal positioning can be used (analog display:block), but the element behaves like a span element, for example. These elements have no interlace, no definable width and can therefore be on the same line as other inline elements. This is important, so that the combination of a position specification (left) and the transformation (translate3d) can do the “magic” together.

Transformations with position specification

Position information and transformations behave differently. The specification “left” refers to the parent element, but “translate” refers to the element itself. This is particularly important, cause we need to specify percents values.

An example: If we would set a transform: translate3d(100%, 0%, 0px) which seems to be identical to “left:100%” at from-range, the text starts much too far to the right in the off. With each “run out” on the left, it takes a long time for the text on the right to start again. The 100% of the ticker element are absolutely (in pixels) larger than the 100% of the browser window. With left:100% and translate3d(0%, 0%, 0px) we ensure that the starting point is positioned exactly at 100% of the browser width. But that is not enough. The text does not run through completely as described above and starts again too early. So we have to explicitly declare the end position as left:0% with -100% transformation to ensure a complete cycle.

Events in the body-tag

To start the Javascript processing only after the HTML part is completely loaded, we use the event onLoad in the body tag. This event calls the start() function, which initiates a process, which we will describe in more detail below.

The Javascript-Algorithm

At the beginning we construct an algorithm consisting of four steps.

  1. Get the RSS as JSON-Text
  2. Convert the JSON response to a javascript object
  3. Extract the ticker text from javascript object
  4. Display the ticker

JSON (JavaScript Object Notation) is a standard text format for the uncomplicated exchange of structured data.

Bypass SOP

For the examples we use our own RSS feed at https://smil-control.com/blog/feed/. There are several solutions for querying this without coming into conflict with the browser security concept (Same Origin Policy) mentioned above. E.g. CORS (Cross-Origin Resource Sharing), JSONP or even a separate server-side script. However, these solutions have their advantages and disadvantages and require additional work whose explanations would go beyond the scope of this tutorial. Therefore we decided to use the Yahoo Query Language (YQL). Yahoo makes this interface freely available to the general public at https://developer.yahoo.com/yql. For example: The request ‘select title, description from rss where url=”https://smil-control.com/blog/feed”&format=json’ delivers us all title and description tags of the feed in JSON format.

Get the RSS as JSON-Text

The function getRSS is called with the url of the RSS feed and looks like this:

function getRSS(url)
{
	var request_url = 'https://query.yahooapis.com/v1/public/yql?q=select title from rss where url="'+url+'"&format=json';
	var MyRequest = new XMLHttpRequest();
	MyRequest.open("GET", request_url, true);
	MyRequest.onload = function (e)
	{
		if (MyRequest.readyState === 4)
		{
			if (MyRequest.status === 200)
			{
				handleTicker(MyRequest.responseText);
			}
			else
			{
				console.error(MyRequest.statusText);
			}
		}
	};
	MyRequest.onerror = function (e)
	{
		console.error(MyRequest.statusText);
	};
	MyRequest.send(null);
}

First, the query url is assembled. Since only the title as headline is relevant for the scroll bar, we only request that. New XMLHttpRequest() creates a new object (here: MyRequest) for a data query via an url. The function open() initializes a GET request asynchronously and finally sends it (send()). GET is a simple HTTP request to request data from a server. In principle it is like entering something in the address bar of your browser. Asynchronous means that after the query is sent, the script does not wait for the response to continue. These are the so-called AJAX queries common in modern web applications. Asynchronous queries are executed in the background and do not block the browser. It can then continue with other things, such as drawing up the page layout.

Event handler

Furthermore, we create two so-called event handler functions. Onerror() is activated if there is an error e.g. the Yahoo-Url is not reachable. If this happens, we write the error message in the console. The onload() function checks whether a result is available. I.e. the readyState property of the query takes the value 4. Next, the so-called status code of the response is checked by Yahoo. If everything is fine, the status code is set to 200 and the script passes the text of the response to the handleTicker() function for further processing. Otherwise, an error message is displayed in the console.
The handleEvent function now takes over the further steps of the algorithm determined above.

function handleTicker(response)
{
	var feed_obj    = JSON.parse(response);
	var ticker_text = createTickerOutput(feed_obj);
	displayTicker(ticker_text, feed_obj.query.count);			
}

Convert the JSON response to a javascript object

The text in JSON format passed by the getRSS() function is converted to a Javascript object with JSON.parse(response). Attention! Old tutorials may refer to eval(), since JSON.parse was only introduced as ECMA 5.1 standard in December 2009. Eval() can be used to execute Javascript code and convert JSON to objects. Please try to avoid using it, because it also carries the risk of unintentionally infiltrating malicious code. JSON.parse() is more secure and executes faster.

Extract the ticker text from javascript object

function createTickerOutput(feed_obj)
{
	var ticker_text = "";
	for (var i = 0; i < feed_obj.query.count; i++)
	{
		ticker_text += feed_obj.query.results.item[i].title+ " +++ ";
	}
	return ticker_text;
}

The function loops through all messages (items) of the feed object step by step. The title field for the headline is extracted and added to the ticker_text string. In ticker_text all headlines are separated by a “+++” after the end of the loop. The content of the ticker_text variable is returned and will be used for the scrolling text.

Determine the animation time

The duration of an animation must be set in the stylesheet. A fixed time can cause problems with different text lengths. CSS3 running texts with RSS could contain 20 headlines and more. These are certainly not easy to read in 10 seconds. On the other side: If the time is too high, the ticker scrolls painfully slowly. This can be compensated by a functionality that determines the animation time depending on the number of headings:

 
function getAnimDurationInSeconds(num)
{
	var seconds = num*10;
	return seconds.toString()+"s";
}

To calculate the animation time, we apply 10s reading time per headline. Five headlines, that’s 50 seconds. Good headlines usually consist of 4-8 words. So 10 seconds time to read a smooth scrolling text should be approximately appropriate. You can also “play around” with this factor until the speed meets your requirements.

Wage of trouble

In the last step we fill the ticker-div with the text extracted above and set the animation time.

function displayTicker(ticker_text, num_headlines)
{
	var ticker                     = document.getElementById("ticker");
	ticker.innerHTML               = ticker_text;
	ticker.style.animationDuration = getAnimDurationInSeconds(num_headlines);
} 

First we initialize a variable called ticker to address the ticker-div. Next, the div gets the content text and finally we set the calculated animation time in the CSS.
Click on css3_animations_rss.html to view the CSS3 running texts with RSS. You will see that the ticker always behaves the same. Even if you change the width of your browser window during the process.

What happens next?

In the next post on Tuesday, June 12th, we will create a horizontal scrolling text based on HTML5 canvas and fill it also from an RSS feed.
If you have any questions or comments, please do not hesitate to contact us.

Leave a Reply

Your email address will not be published. Required fields are marked *