Question

I am converting a html site to an Ember.js app and have run into an issue with the jQuery Cycle slideshow plugin. I have around 10 slideshows on the site, so I want to have one partial which I can use everywhere and pass data to.

This all works nicely, the passing data part anyway, but the slideshow never gets initialized and fails. Every time the page loads I get the same "[cycle] terminating; zero elements found by selector" error and the slideshow never renders.

The slideshow.js file is included in the head of the html document, I have tried moving this to the footer and deferred loading but the error persists.

How can I amend my code so that the slideshow is initialized when a template is loaded as I feel the issue may be trying to initiate on $(document).ready().

<script type="text/x-handlebars" data-template-name="components/main-slider">
<div class="slider_wrap">
  <div id="slider">
    {{#each sliders}}
      <div class="slider_area slider0{{unbound number}}">
        <div class="slider_inner">
          <div class="inner0{{unbound number}}">
            <img {{bind-attr src="image" alt="image"}} class="nosp"/>
            <img {{bind-attr src="sm_image" alt="sm_image"}} class="sp"/>   
          </div>
       </div>
     </div>
    {{/each}}               
  </div>
</div>

slideshow.js

jQuery(document).ready(function($){
    $('#slider').cycle({
        slideResize:0
    });
    $('#slider').css({
        'width':'auto'
    });
    $(window).resize(function(){
        var height = $('.slider_area').height();
        $('#slider').css("height",height + 'px');
    });
});

app.js

App.IndexRoute = Ember.Route.extend({
    model: function() {
        return App.INDEXSLIDERS;
    }
});

// Data //

App.INDEXSLIDERS = [
    {
        number: 1,
        image: "images/sliders/index/slide1.jpg",
        sm_image: "images/sliders/index/slide1_sm.jpg"
    },
    {
        number: 2,
        image: "images/sliders/index/slide2.jpg",
        sm_image: "images/sliders/index/slide2_sm.jpg"
    },
    {
        number: 3,
        image: "images/sliders/index/slide3.jpg",
        sm_image: "images/sliders/index/slide3_sm.jpg"
    },
    {
        number: 4,
        image: "images/sliders/index/slide4.jpg",
        sm_image: "images/sliders/index/slide4_sm.jpg"
    }
];

Note

Have to add

slideExpr: '.slider_area'

to the call to .cycle() otherwise the plugin will try and slide the handlebar scripts inserted before and after each slide.

Was it helpful?

Solution

Yeah, you're on the right track, document onload will happen before the page has been completely rendered.

You'll want to add that logic into the didInsertElement hook of the component. Then you can scope it to that particular component instance. Additionally I changed it from and id to a class so you can grab that instance.

Component

App.MainSliderComponent = Em.Component.extend({
  didInsertElement: function(){
    var thisSlider = this.$('.main_slider');

    thisSlider.cycle({
      slideResize:0
    });
    thisSlider.css({
        'width':'auto'
    });
    $(window).resize(function(){
        var height = thisSlider.height();
        thisSlider.css("height",height + 'px');
    });
  }
});

Template

<script type="text/x-handlebars" data-template-name="components/main-slider">
<div class="slider_wrap">
  <div class="main_slider">
    {{#each sliders}}
      <div class="slider_area slider0{{unbound number}}">
        <div class="slider_inner">
          <div class="inner0{{unbound number}}">
            <img {{bind-attr src="image" alt="image"}} class="nosp"/>
            <img {{bind-attr src="sm_image" alt="sm_image"}} class="sp"/>   
          </div>
       </div>
     </div>
    {{/each}}
  </div>
</div>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top