View RSS Feed

Beverleyh

SiteShow with Controls - Fade-in a list of web pages/URLs as a fullscreen 'SiteShow'

Rate this Entry
Last year I wrote about my digital signage work and the mechanics of how I displayed news and updates on a web page in a Simple Sweep-in News Scroller (CSS3/JS). The web page was displayed on a large TV screen that was mounted in a lobby/reception area, with several more installations visible around the grounds. At the time, I didn't explain that along with a web page of scrolling updates, there were many additional web pages that all displayed on a cycle, with each page redirecting to the next after a few minutes had passed. I used a simple countdown and redirect script, but the same sort of thing could also have been accomplished with a meta refresh tag;
Code:
<meta http-equiv="refresh" content="30; URL=another-page.htm">
Although this approach was fine back then, it has since created a few problems with scheduling because there is no easy way to load in new screens and manage ad-hoc content from one location; The "schedule" is scripted on a screen-to-screen basis with each URL hardcoded into the preceding web page. So I went back to the drawing board to write a self-contained 'SiteShow' script...

Requirements:
1 - Manage all pages from one location (including display order, ad-hoc additions and regular content)
2 - Pages must have individual display duration/timings
3 - A way for admins to pause/play/navigate screen content to test new schedules


DEMO - SiteShow with Controls (no jQuery): http://fofwebdesign.co.uk/template/_...w-controls.php


Displaying URLs as a 'SiteShow'
As luck would have it, I had recently revisited the earlier sweep-in news scroller and furnished it with navigation controls - Sweep-in News Scroller with Controls - and I thought this would be the perfect basis for my latest project, but instead of using the script to reveal a new list item of text into the scroller, I would use it to reveal a new web page into an iFrame.

One main page, containing a list of URLs, and an iFrame in which to display them, satisfies point 1 from my list of requirements. Additionally, having the 'SiteShow' scripts run from instructions that come from the menu markup would also go part-way in solving point 3;
Code:
<ul>
	<li data-src="daily-news.htm" >Daily News</li>
	<li data-src="contact-us.htm" >Contact Us</li>
	<li data-src="opening-hours.htm" >Opening Hours</li>
</ul>
Note how each web page URL is defined inside the data-src attribute of every list item. With this in mind I took the script from the Sweep-in News Scroller with Controls page and, with a few minor alterations, passed this data-src attribute to the iFrame src within the show() function;
Code:
(function(){
	var qselector = '#menu ul',
	    time = 5000,
	    item = document.querySelectorAll(qselector + ' > li'), // each li as menu item
	    int = setInterval(next, time), i = 0, go = 1, 
	    content = document.getElementById('content'),
	    pause = document.querySelector(qselector + ' + .controls .pause');

	function show(num){
		i = (num + item.length) % item.length;
		content.src = item[i].getAttribute('data-src');
		}
	function stop(){
		go = 0; clearInterval(int);
		pause.innerHTML = 'Play';
		}
	function start(){ 
		go = 1; int = setInterval(next, time);
		pause.innerHTML = 'Pause'; 
		}
	function next(){ show(i+1); }
	function prev(){ show(i-1); }
	pause.addEventListener("click", function(){ go ? stop() : start(); });
	document.querySelector(qselector + ' + .controls .next').addEventListener("click", function(){ next(); stop(); });
	document.querySelector(qselector + ' + .controls .prev').addEventListener("click", function(){ prev(); stop(); });

	content.src = item[0].getAttribute('data-src'); // load 1st item
})();
So, with very little effort, I'd quickly achieved most of what I set out to do. Here's a basic demo of how that looks so far: http://jsbin.com/sederuhoxi/1/edit?html,js,output

Individual 'Slide' duration
The next challenge was to tackle point 2 on my list of requirements and introduce individual timings/durations for each page, so again, I opted for another data attribute on each menu list item - this time called data-sec;
Code:
<ul>
	<li data-sec="5"  data-src="daily-news.htm" >Daily News</li>
	<li data-sec="10" data-src="contact-us.htm" >Contact Us</li>
	<li data-sec="12" data-src="opening-hours.htm" >Opening Hours</li>
</ul>
I also revised the script so that it initially set a 'time' variable from the 1st items data-sec attribute and passed it as the time interval to the 'int' variable;
Code:
(function(){
	var qselector = '#menu ul',
	    item = document.querySelectorAll(qselector + ' > li'), // each li as menu item
	    time = item[0].getAttribute('data-sec') * 1000,
	    int = setInterval(next, time), i = 0, go = 1, 
	    content = document.getElementById('content'),
	    pause = document.querySelector(qselector + ' + .controls .pause');

	function show(num){
		clearInterval(int);
		i = (num + item.length) % item.length;
		time = item[i].getAttribute('data-sec') * 1000; 
		int = setInterval(next, time); 
		content.src = item[i].getAttribute('data-src');
		}
	function stop(){
		go = 0; clearInterval(int);
		pause.innerHTML = 'Play';
		}
	function start(time){ 
		go = 1; int = setInterval(next, time); next();
		pause.innerHTML = 'Pause'; 
		}
	function next(){ show(i+1); }
	function prev(){ show(i-1); }
	pause.addEventListener("click", function(){ go ? stop() : start(time); });
	document.querySelector(qselector + ' + .controls .next').addEventListener("click", function(){ next(); stop(); });
	document.querySelector(qselector + ' + .controls .prev').addEventListener("click", function(){ prev(); stop(); });

	content.src = item[0].getAttribute('data-src'); // load 1st item
})();
Now, because the time interval must change for each slide, it must be cleared first in the show() function, where it can then be reset by a new data-sec attribute value, and set as a new time interval. Here's another basic demo to see the individual timing changes in effect: http://jsbin.com/heburumeme/1/edit?html,js,output.

Requirement 2 solved! Now to tidy-up requirement 3...

Admin menu
The admin menu was mostly working fine at this stage, in the sense that we can navigate back and forth and pause/play the active 'slide', but the list items don't actually do anything. I decided to add a small loop to turn the list of titles into clickable links;
Code:
for (var li = 0; li < item.length; ++li){
	item[li].addEventListener("click", function(){ stop(); content.src = this.getAttribute('data-src'); });
	}
Again, I'm using the data-src attribute of the clicked list item and passing it to the iFrame's src.

At this stage, ALL requirements have been satisfied, but the job isn't quite finished. Visually it looks very dry, and of course there is a small amount of CSS needed to size the iFrame to fullscreen, and make the admin menu look better. That's been done in the final demo, along with a fade-in mask (a technique used in my content filter scripts: single selection, multi-selection) to add a bit of polish to the whole thing.

DEMO - SiteShow with Controls (no jQuery): http://fofwebdesign.co.uk/template/_...w-controls.php

I hope you find the script useful. When projected through a TV in your lobby or reception area it can make for a very eye-catching and informative visitor display.

Caveats
Because this script displays URLs through an iFrame, please bear in mind that if a "break out of frames" script is present in one of the displayed web pages, it will break the SiteShow.

Submit "SiteShow with Controls - Fade-in a list of web pages/URLs as a fullscreen 'SiteShow'" to del.icio.us Submit "SiteShow with Controls - Fade-in a list of web pages/URLs as a fullscreen 'SiteShow'" to StumbleUpon Submit "SiteShow with Controls - Fade-in a list of web pages/URLs as a fullscreen 'SiteShow'" to Google Submit "SiteShow with Controls - Fade-in a list of web pages/URLs as a fullscreen 'SiteShow'" to Digg

Updated 08-11-2016 at 07:27 AM by Beverleyh (formatting code a little better)

Categories
JavaScript & Ajax , Web Design issues

Comments

  1. molendijk's Avatar
    That's very nice. I guess the impossibility of clicking on items of the individual external pages (in the show) is intentional?
    The way you reveal new web pages into an iframe has a disadvantage, though. When we let the show go on for a while, then new entries are constantly added to the browser's history, which makes it hard to go back to a preceding window via the browser's back button. We're captured in the show, so to speak. Couldn't you make it so that new iframed pages are added via replace, not via href?
  2. Beverleyh's Avatar
    Thanks for the feedback

    I guess the impossibility of clicking on items of the individual external pages (in the show) is intentional?
    Yes, the "mask" is always present, but transparent, so this acts as a blocking mechanism for the framed page content. The idea is that the admin (the person triggering the hover menu) wouldn't need to interact with the pages that are showing - just the SiteShow hover menu, to test the schedule via a computer. The SiteShow is being displayed to all other 'users' via a TV screen where interaction isn't necessary.

    The way you reveal new web pages into an iframe has a disadvantage, though. When we let the show go on for a while, then new entries are constantly added to the browser's history, which makes it hard to go back to a preceding window via the browser's back button. We're captured in the show, so to speak. Couldn't you make it so that new iframed pages are added via replace, not via href?
    If you wanted to display the SiteShow via a website then yes, the replace() method might be a better choice, but this is for display via a TV (no controls) so the browser history isn't an issue in the intended context. All users (except the admin) are looking at the output via a mounted TV and have no way of interacting - they look but don't touch