Reputation: 1232
I am making an application for showing a synchronized HTML5 slideshow to about 50 spectators in a wireless LAN with no internet access.
I run a Node.js server in one of the computers and connect with the 50 clients via Socket.IO (Btw, only one of them controlls the presentation).
The hardware is a domestic wireless 802.11b/g router and 50 mobile devices (tablets, netbooks, smartphones).
When the slideshow starts, it takes too long (about 10 minutes or more for a 5 MB slideshow) for the clients to see it, since the router has to send the complete slideshow to all the clients at the same time.
<html>
<head>
<title>My Slideshow</title>
<script src="javascripts/slidesplayer.js"></script>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
<div id="slides-containter">
<div class="slide" id="slide_1">
<!--Contents such as images, text, video and audio sources -->
</div>
<div class="slide" id="slide_2">
<!--Contents -->
</div>
<!--A bunch of slides here-->
</div>
<script>
// Here I load the slides
</script>
</body>
</html>
At the beginning, I would like to load the slides-container
element completely empty.
Then, as I advance through the slideshow, I'd like to GET from the server the div
representing the next slide, and append it to the DOM so that only when that is done, the client starts to download the pictures and othet stuff only for that slide (thus, decreasing significantly my network overload).
Another relevant fact is that the slideshow (including the slidesplayer.js
) is automatically generated from an external software that parses PowerPoint presentations to this HTML5 format and that we will use a lot of presentations that are already made in PowerPoint.
My first impression is that I should accomplish this by using jQuery-ajax, but I don't know exactly how to do it the good way, since my idea is just copying the div.slide
elements in separate files.
Update: This answer suggests using jQuery for DOM manipulation before displaying. It seems that jQuery requests the resources everytime you manipulate a DOM object, even if it is not inserted into your current DOM. So, one possible solution would be working only with strings. You can see more about this issue in this and this questions.
Upvotes: 1
Views: 1327
Reputation: 1232
As I said in the question, manipulating DOM elements will cause the browser to download the resources, even if you don't insert the elements that use that resources in your DOM.
In my case, the best solution I could make was to use some sort of lazy loading at least for the img
tags (but it could be easily extended for other tags, such as audio
and video
).
What I did was replacing replacing the src
attribute with another name (xsrc
in this case) and adding a custom empty src
attribute to all img tags.
<img id="someImg" src="#" xsrc="foo.png"></img>
Then, with jQuery I changed the src
attribute value to that of xsrc
whenever I needed to dowload the image.
// When I want the image to be downloaded from the server
$('#someImg').attr( 'src' , $('#someImg').attr('xsrc') )
You can see more about the idea behind this in the questions I already mentioned (this and this).
Upvotes: 1
Reputation: 16466
One solution would be to treat this as a front-end solution. The front-end should arguably only eat as much as it can take at any one time.
I'm assuming it's external resources (imagery etc) as opposed to the slideshow markup itself that's making up the most of those 5MB, in which case the DOM should not attempt to call those resources until they are necessary.
I would suggest serving the whole slide document to an ajax call but only introducing the markup to each slide as it is called. Something like this:
$.ajax('path/to/slides', {
async: false,
complete: function ajaxCallback(slidesDOM){
// Pull out the individual slides from your slideshow HTML
$slides = $(slidesDOM).find('.slide');
// For each of these...
$slides.each(function prepareSlide(){
// Store a reference to the slide's contents
var $slideContent = $($(this).html());
// Empty the contents and keep only the slide element itself
var $slideWrapper = $(this).empty();
$slideWrapper
// Put the slide where you want it
.appendTo('.slidesContainer')
// And attach some kind of event to it
// (depending on how your slideware works, you might want to bind this elsewhere)
.on('focus', function injectContent(){
// Put the content in — NOW external resources will load
$slideWrapper.append($slideContent);
// Unbind this function trigger
$slideWrapper.off('focus', injectContent);
});
})
}
});
Upvotes: 2
Reputation: 5090
1) You shouldn't be streaming payloads with SocketIO. Socket is made for low-load. If you need to transmit en-masse, I'd recommend using a standard HTTP AJAX request. Then, you can use Socket.IO to control which slide you are on.
2) Try AngularJS. They've basically done all the thinking for you regarding view switching (which is essentially what you are doing). They have a great tutorial, which helps alot.
3) To simplify you Socket calls, I'd recommend using ConversationJS both client and server side.
Upvotes: 1