Pregunta

I am trying to build up an HTML that is going to be used in a jQuery Cycle carousel plugin that my end users want to use for a product carousel. The plugin requires the HTML to look like this:

<div id="slide-0"><!-- anything in here --></div>
<div id="slide-1"><!-- anything in here --></div>
<div id="slide-2"><!-- anything in here --></div>
<!-- etc. -->

However, the number of products is dynamic. In this case, it's coming from a JSON object like this:

JSON

var productJsonResponse = {
   "products": [{
       "Name": "Bulb"
    },
    {
       "Name": "Wrench"
    },
    {
       "Name": "Hammer"
    },
    {
       "Name": "Screwdriver"
    },
    {
       "Name": "Pliers"
    }]
}

This is the Handlebars template I would like to build. I can't use the default {{#each}} helper, since I need to create the outer "slide" divs. {{#createCarouselSlides}} is a custom helper where the end user enters the number of slides he/she wants to create.

Template

{{#createCarouselSlides 2 products}}
<div id="slide-{{@index}}">
    {{#customFunctionInner 2 ??? products}}
        <div class="product">
            <span class="product-name">{{Name}}</span>
        </div>
    {{/customFunctionInner}}
</div>
{{/createCarouselSlides}}

I figured out how to create the outer div part using a custom helper and looking at the Handlebars source code about how {{#each}} works. But, I am unsure how to pass {{@index}} into an inner custom function (customFunctionInner) where I need to segment my products. For example, if there are 5 products, and the end user wants 2 products per slide, I'll generate 3 slides, but I need the index to be able to know which products go into which slide.

Outer Helper

<script type="text/javascript">
; (function ($, Handlebars, window, document, undefined) {
    Handlebars.registerHelper('createCarouselSlides', function (productsPerSlide, context, options) {
        var result = "",
            data = {};

        // Create the necessary number of slides and populate them with the products in $products.
        for (i = 0; i < Math.ceil(context.length / productsPerSlide); i += 1) {
            data.index = i;
            result += options.fn(context[i], { data: data });
        }

        return result;
    });
})(jQuery, Handlebars, window, document);
</script>

My question is: Can I take {{@index}} from my first helper and simply pass it into another custom helper? And what is the syntax look like?

This would be normally "easy" to do in plain Javascript as a pair of outer (i) and inner (j) for loops, where the outer loop controls the generation of the slide divs and passes i to the inner loop.

¿Fue útil?

Solución

I solved my problem. It required creating a private variable for the index in the outer helper and accessing it in the inner helper, via options.data.index. Since the inner helper is associated with a child template, the inner helper has access to the variable.

Template

{{#createCarouselSlides 2 products}}
    <div id="slide-{{@index}}">
      {{#createCarouselItemr 2 ../products}}
         <div class="product">
            <span class="product-name">{{Name}}</span>
        </div>
      {{/createCarouselItem}}
     </div>
{{/createCarouselSlides}}

Helpers

; (function ($, Handlebars, window, document, undefined) {
    /* Outer function */
    Handlebars.registerHelper('createCarouselSlides', function (productsPerSlide, context, options) {
        var result = "";

        /* Create the necessary number of slides */
        for (var i = 0; i < Math.ceil(context.length / productsPerSlide); i += 1) {
            if (options.data) {
                data = Handlebars.createFrame(options.data || {});
                data.index = i;
            }

            result += options.fn(context[i], { data: data });
        }

        return result;
    });

    /* Inner Function */
    Handlebars.registerHelper('createCarouselItem', function (productsPerSlide, context, options) {
        var result = "",
            currentItemIndex = "";

        /* Create the necessary number of items per slide */
        for (var j = 0; j < productsPerSlide; j += 1) {
            currentItemIndex = (options.data.index * productsPerSlide) + j;
            if (currentItemIndex < context.length) {
                result += options.fn(context[currentItemIndex]);
            }
        }

        return result;
    });
})(jQuery, Handlebars, window, document);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top