简体   繁体   中英

Get HTML elements from a document in the server and show them dynamically in the client

Context

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).

Problem

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.

How my slideshow looks

<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>

What I would like to do

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.

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);
        });
    })
  }
});

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.

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 ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM