Problems, need help? Have a tip or advice? Post it here.
6 posts Page 1 of 1
Hi,

Anybody knows a way to load snippets on click?

My mega menu is Killing my DOM size.

Thanks
Did you ever experiment with dynamic HTML templates?

HTML templates - "Method of declaring a portion of reusable markup that is parsed but not rendered until cloned."

Like so —

Code: Select all
<div class="list-items" ></div>

<script>
const Item = ({ url, img, title }) => `
  <a href="${url}" class="list-group-item">
    <div class="image">
      <img src="${img}" />
    </div>
    <p class="list-group-item-text">${title}</p>
  </a>
`;
//Then you could easily render it, even mapped from an array, like so:

$('.list-items').html([
  { url: '/foo', img: 'foo.png', title: 'Foo item' },
  { url: '/bar', img: 'bar.png', title: 'Bar item' },
].map(Item).join(''));
</script>

The point is to click the menu item and dynamically generate sub-items off the template, filling in the data from JSON. Of course, can be inline generated by Couch. This approach makes draw and redraw very fast, due to simplified HTML. I don't have a complete solution for mega menu, just a practical example which I used.

Browser support https://caniuse.com/template

Couch can generate JSON easily —

Code: Select all
<cms:show_repeatable 'schedule' as_json='1' />

Which I used in the following setup —

Code: Select all
<table>
    <thead>
        <tr>
            <th></th>
            <th>September - May</th>
            <th>June - August</th>
        </tr>
    </thead>

    <tbody>
    </tbody>
</table>


<script>
    const Item = ({ my_day,
                    my_winter_off_day,
                    my_winter_opening_time,
                    my_winter_closing_time,
                    my_summer_off_day,
                    my_summer_opening_time,
                    my_summer_closing_time }) => `
        <tr>
            <td>${my_day}</td>`
            + ( my_winter_off_day ? `<td>Closed</td>`: `<td>${my_format(my_winter_opening_time)}-${my_format(my_winter_closing_time)}</td>` )
            + ( my_summer_off_day ? `<td>Closed</td>`: `<td>${my_format(my_summer_opening_time)}-${my_format(my_summer_closing_time)}</td>` ) + `
        </tr>
    `;

    //Then you could easily render it, even mapped from an array, like so:
    $('tbody').html(<cms:show_repeatable 'schedule' as_json='1' />.map(Item).join(''));

    function my_format(str){
        return new Date(str).toLocaleTimeString([],{ hour: '2-digit', minute:'2-digit', hour12: true});
    }
</script>


Above examples used jQuery with map function;

pure JavaScript solution uses importNode function like that —

Code: Select all
<table id="producttable">
  <thead>
    <tr>
      <td>UPC_Code</td>
      <td>Product_Name</td>
    </tr>
  </thead>
  <tbody>
    <!-- existing data could optionally be included here -->
  </tbody>
</table>

<template id="productrow">
  <tr>
    <td class="record"></td>
    <td></td>
  </tr>
</template>


<script>
    // Test to see if the browser supports the HTML template element by checking
    // for the presence of the template element's content attribute.
    if ('content' in document.createElement('template')) {

        // Instantiate the table with the existing HTML tbody
        // and the row with the template
        var t = document.querySelector('#productrow');

        // Clone the new row and insert it into the table
        var tb = document.querySelector("tbody");
        var clone = document.importNode(t.content, true);
        td = clone.querySelectorAll("td");
        td[0].textContent = "1235646565";
        td[1].textContent = "Stuff";

        //setTimeout(tb.appendChild(clone), 2000);
        setTimeout(function(){ tb.appendChild(clone); }, 1000);

        // Clone the new row and insert it into the table
        var clone2 = document.importNode(t.content, true);
        td = clone2.querySelectorAll("td");
        td[0].textContent = "0384928528";
        td[1].textContent = "Acme Kidney Beans 2";

        //setTimeout(tb.appendChild(clone2), 2000);
        setTimeout(function(){ tb.appendChild(clone2); }, 1500);
        //tb.appendChild(clone2);

    } else {
      // Find another way to add the rows to the table because
      // the HTML template element is not supported.
    }
</script>


- - -

I have also seen some code based on loading a menu item via Ajax, but I would never recommend it.

- - -

Hope you can dig something out of the samples. Please post your findings too.

:)
Trendoman, thanks, but I have no idea what you're talking about, nor how that works. :D

I was more thinking in the lines of the jQuery .load() function that would work for snippets.
Paolo, using jQuery.load() can work but would mean making an AJAX request (to a Couch script on server that generates the sub-menu) each time an empty menu-item is clicked - this, I think, will result in a noticeable delay as users are accustomed to seeing menus fly out as soon as they are clicked.

What @trendoman is suggesting is having all those sub-menus (either in fully rendered HTML form or in JSON form that can be rendered client-side) within <template> tags (https://developer.mozilla.org/en-US/doc ... t/template) which " is a mechanism for holding HTML that is not to be rendered immediately when a page is loaded but may be instantiated subsequently during runtime using JavaScript.".

This way your DOM gets populated only as and when required.
Unfortunately, when it comes to JavaScript, there is not much I'd be able to help you with but, I hope, someone from the community can chip in.
Hi KK,

Thanks, I failed to understand what Trendoman meant.

Ok, I got it.

Simple:

In the menu:
Code: Select all
<li><a on="tap:menumoi" onclick="showContent()">Tableaux Modernes</a></li>

To acquire the template and open the AMP light box

And in the footer:
Code: Select all
<template><cms:embed 'menulightbox.html' /></template>
<script>
function showContent() {
  let temp = document.getElementsByTagName("template")[0];
  let clon = temp.content.cloneNode(true);
  document.body.appendChild(clon);
}
</script>


Works like a charm, my PSI score came back normal.

Thanks guys, I didn't even know it existed.
Great! Thanks for updating us.
6 posts Page 1 of 1