#1
  1. Banned (not really)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Dec 1999
    Location
    Caro, Michigan
    Posts
    14,814
    Rep Power
    4536

    JQuery - Repeating a templated <li> efficiently.


    So what I have works fine, but I have a feeling there's a more efficient or straight-forward way to accomplish this.

    What I have is this div and the inner <li> will need to be repeated based on the data returned from a JSON query to my PHP script.
    Code:
    <div class="notification" id="notification">
    	<span id="no_config_notice" style="display:none;">No emulator configuration is currently set on any interface.</span>
    	<ol id="config_notice" style="display:none;">
    		<li style="line-height:2em;font-style:italic;">Current Emulator Configuration:</li>
    		<li id="interface_config">
    			<span class="delete" id="{interface}">✖</span>
    			<span>Interface &lt;{interface}&gt;: </span>
    			<span id="delay">delay {delay}{delay_unit} </span>
    			<span id="jitter">jitter {jitter}{jitter_unit} </span>
    			<span id="loss">loss {loss}% </span>
    			<span id="rate">bandwidth {rate}{rate_unit}</span>
    		</li>
    	</ol>
    </div>
    Based on the data, the list of interfaces may or may not need to show each of those <span> elements. If there is no loss or rate setting, for example, I don't want those elements shown.

    A sample of the data returned:
    Code:
    {"enp0s3":{"delay":500,"delay_unit":"ms","rate":"12","rate_unit":"Mbit"}}
    And the JQuery code that runs the template replacement. More than one interface could be returned, hence the .each() loop.
    This just doesn't feel right, though, since there's CSS & HTML in my javascript code as strings.
    Code:
    function load_status(data) {
    	var count = 0;
    	hide = "style=\"display:none;\"";
    	
    	html = $("#interface_config").html();
    	$("#interface_config").remove();
    	
    	
    	$.each(data, function(index, info) {
    		output = html.replace(/{interface}/g, index);
    
    		if(info.delay === undefined) {
    			output = output.replace(/id="delay"/g,hide);
    		} else {
    			output = output.replace(/{delay}/g, info.delay);
    			output = output.replace(/{delay_unit}/g, info.delay_unit);
    		}
    		
    		if(info.jitter === undefined) {
    			output = output.replace(/id="jitter"/g, hide);
    		} else {
    			output = output.replace(/{jitter}/g, info.jitter);
    			output = output.replace(/{jitter_unit}/g, info.jitter_unit);
    		}
    		
    		 if(info.loss === undefined) {
    			 output = output.replace(/id="loss"/g, hide);
    		 } else {
    			 output = output.replace(/{loss}/g, info.loss);
    		 }
    		 
    		 if(info.rate === undefined) {
    			 output = output.replace(/id="rate"/g, hide);
    		 } else {
    			 output = output.replace(/{rate}/g, info.rate);
    			 output = output.replace(/{rate_unit}/g, info.rate_unit);
    		 }
    		 
    		$("#config_notice").append('<li>'+output+'</li>');
    		count++;
    	});
    
    	if(count==0) {
    	  $("#no_config_notice").show();
    	} else {
    	  $("#config_notice").show();
    	}
    }
    
    function ajax_getInterfaceStatus() {
      $.ajax({
          url: "tacem.php",
          data: { action: "status"},
          method: "POST",
          dataType: "json",
          success: load_status
      });
    }
    Like I said, this works, but is there a more efficient way to do it? I'll eventually be adding more <span> components to the display, as there are still about 10 more interface elements that may or may not be set.

    -John
    -- Cigars, whiskey and wild, wild women. --
  2. #2
  3. Banned (not really)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Dec 1999
    Location
    Caro, Michigan
    Posts
    14,814
    Rep Power
    4536
    This is what I ended up with through help on another forum. Handlebars was recommended as the templating engine, so I took that advice. Beyond that, parseHTML() seemed to be the missing part. That turned the raw HTML back into an object I could then .show() and .hide() portions of. This works for me.

    Code:
    function load_status(data) {
    	
    	var output = [];
            var template = Handlebars.compile($('#interface_config').html());
            $('#interface_config').remove();
    
            $.each(data, function(index, info){
          	  info.interface = index;
              var html = template(info);
              var $result = $("<li>").append($.parseHTML(html));
    
              if(info.delay === undefined) {
                  $result.find('.delay').hide();
              }
    
              if (info.jitter === undefined){
                  $result.find('.jitter').hide();
              }
    
              if (info.loss === undefined){
                  $result.find('.loss').hide();
              }
    
              if (info.rate === undefined){
                  $result.find('.rate').hide();
              }
    
              output.push($result);
            });
    
            if (output.length){
              $('#config_notice').append(output).show();
            } else {
              $('#no_config_notice').show();
            }
    }
    -- Cigars, whiskey and wild, wild women. --

IMN logo majestic logo threadwatch logo seochat tools logo