The js/css doesn't get placed on the page for cached blocks. I know this is a very common issue across all drupal modules but there should be a solution.

Would a solution be to add in the JS in a block_view_alter hook?

Comments

minorOffense’s picture

Status: Active » Postponed (maintainer needs more info)

Hmm, you could always include the library manually with drupal_add_library in your template.php file. Either in template_preprocess_html or template_preprocess_page

So when you enable the cache in views FlexSlider blocks stop working? Or when you enable the block cache in the Config/Performance page?

joelcollinsdc’s picture

Yep, that would be one way to do it. Basically whenever you do something in a theme() function, I think the intention is (or, was) to only affect markup of the item being themed. So alterations made to the page js/css during theming aren't cached properly.

Yes, so what we found was the first time a user viewed a page, the flexslider block worked. Then when the user revisited the page (not a cache anonymous page, but a page where the block response was cached), the html for the flexslider was found but the JS didn't get loaded.

Since the functionality of block caching is to always call hook block alter regardless of caching, I think a pretty clean solution would be to also add JS in there so a cached block will still work.

minorOffense’s picture

That makes sense to me. The only issue though is determining the id of the blocks with FlexSlider in them from views so we can perform the alter properly. Any ideas on that?

Devin Carlson’s picture

Title: Flexslider blocks can't be cached » Flexslider library should be #attached to content to allow caching
Component: Views Style Plugin » Code
Category: bug » task
Status: Postponed (maintainer needs more info) » Active

Flex Slider currently uses calls libraries_load() to load the required CSS/JS (which is incompatible with caching). The library should use #attach to attach itself to fields/views/blocks etc.

For example:

'#attached' => array(
  'libraries_load' => array(
    array('flexslider'),
  ),
),
Devin Carlson’s picture

Status: Active » Postponed

Attaching the Flexslider library to the field formatter is straightforward but I've run into a wall when it comes to attaching the library to the view style plugin.

See #1894736: Cannot use #attached to add general CSS/JS/Library to a View for the issue and #1811828: Use #attached to find the css/js of a view for the change that went into Views for D8 core.

I'm marking this postponed unless someone has a solution. :)

minorOffense’s picture

Want to post your patch thus far? Or I can create a branch specific to this task.

aimeerae’s picture

+1. We are getting similar symptoms with caching + views + FlexSlider. I'll double check on our sites, but I'm pretty sure it happens if you use either the View Format of "FlexSlider" or the Views Slideshow with the Slideshow Type = FlexSlider. We noticed this heavily using the two FlexSliders on the page for a Slide and Carousel of thumbnails for navigation.

We also are using a full cache stack: views cache, Drupal page cache, Advanced Aggregation for CSS / JS aggregation, Redis, APC, and Varnish. I'll be happy to test if a patch is up!

minorOffense’s picture

Component: Code » Views Style Plugin

So for fields this should be working. However with Views it seems to be an issue with Views itself. Not much for us to do except link out to the work arounds.

sidharthap’s picture

Issue summary: View changes

+1 to #7, i am also facing the same issue. Varnish cache, views, blocks and aggregate.js. The flexslider.load.js is not present on the page some time. After clearing varnish cache 2 3 times problem goes.
Is there any workaround of this issue ?

joelcollinsdc’s picture

This is as far as I got with this. Basically I can't figure out how to remove the add libarry stuff out of the theme funciton and move it to a block_view or something that is actually part of the block generation so you can access #attached.

function mymodule_block_view_alter(&$data, $block) {
  if ($block->delta == 'myblock') {
    dpm($block);
    dpm($data);
    $data['content']['#attached'] = array(
      'libraries_load' => array(
        array('flexslider'),
      ),
      'css' => array(
        'asdf.css',
      ),
      'js' => array(
        drupal_get_path('module', 'flexslider') . '/assets/js/flexslider.load.js',
      ),
    );
  }
}

Everything works here except loading the specific optionset javascript... (this stuff)

  // If the ID or optionset aren't set, it is assumed the settings will be set
  // manually via the calling module/theme
  if (!empty($id) && !empty($optionset)) {
    // JavaScript settings
    $js_settings = array(
      'optionsets' => array(
        $optionset->name => $optionset->options,
      ),
      'instances' => array(
        $id => $optionset->name,
      ),
    );
    // @todo add alter hook for optionset
    drupal_add_js(array('flexslider' => $js_settings), 'setting');
joelcollinsdc’s picture

just in case this helps someone...

// Flexslider can't be cached... see https://www.drupal.org/node/1873970
// i'm just using a normal views block
function congress_office_location_settings_block_view_alter(&$data, $block) {
  if ($block->bid == 'views-congress_offices-footer_offices') {
    $optionset = flexslider_optionset_load('congress_footer_offices_block');
    // JavaScript settings
    $js_settings = array(
      'optionsets' => array(
        $optionset->name => $optionset->options,
      ),
    );
    $inline_js = <<<EOT
(function($) {
  $(".footer-offices-block .view-content").flexslider(Drupal.settings.flexslider.optionsets["congress_footer_offices_block"]);
}(jQuery));
EOT;
    $data['content']['#attached'] = array(
      'libraries_load' => array(
        array('flexslider'),
      ),
      'js' => array(
        array(
          'data' => array('flexslider' => $js_settings),
          'type' => 'setting',
        ),
        array(
          'data' => $inline_js,
          'type' => 'inline',
          'scope' => 'footer',
        ),
      ),
    );
  }
}
Diane Bryan’s picture

joelcollinsdc, any chance you can explain where this code goes, and whether you've actually solved the problem by using it? I assume I'd have to change the machine name for the views block I'm trying to load. I'm up a creek right now.. having to turn off all block caching, varnish, etc.

joelcollinsdc’s picture

so i turned off the flexslider display and just used a normal view (unformatted list?). THen I used a views alter hook to inject the appropriate flexslider javascript into the #attached property, so when the block gets cached the javascript gets caced as well.

and I hate to say this but if you aren't sure where that code goes... its probably going to be hard for you to get all this to work together. This is an alter hook, its in a module (but could be placed in template.php or whatever).

basically, i solved the problem by not bypassing the flexslider display. so I think for this to work for you, youd have to modify the above code

feel free to send your code to my name without the dc at gmail and i woudl take a look.