There is a form for configuring options for the flexslider. It would be great if it allowed for adding callback functions. Is there a way to override the ctools plugin? Or, does the module need a patch to accomplish that?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

minorOffense’s picture

Status: Active » Postponed (maintainer needs more info)

What kind of callback are you looking for? Do you mean in javascript when certain actions occur in the slideshow? Or a hook of some kind in PHP to act on something?

wiktorb’s picture

There are 4 callback functions in flexslider configuration:

start: function(){}, //Callback: function(slider) - Fires when the slider loads the first slide
before: function(){}, //Callback: function(slider) - Fires asynchronously with each slider animation
after: function(){}, //Callback: function(slider) - Fires after each slider animation completes
end: function(){} //Callback: function(slider) - Fires when the slider reaches the last slide

but you can't setup it in current release unless you hack the module. It would be nice if I can add js file with callback functions to theme, and then specify functions names in configuration set admin/config/media/flexslider/edit/set_name

iamsquared’s picture

They are js functions that come standard with flexslider... any plans to integrate them?

minorOffense’s picture

Status: Postponed (maintainer needs more info) » Postponed

I'm a little hesitant adding a set of text areas where a user can enter arbitrary javascript to be executed.

I'll give it some thought, see how I might be able to get this in.

Adam S’s picture

I'm a little hesitant adding a set of text areas where a user can enter arbitrary javascript to be executed.

I was just wondering if there was a way to do this in code? I'm sure there is a way but I couldn't figure it out.

eduardo.flores’s picture

I was also looking for more than a month a way to use the after callback function, and right now I have just got it working. I'm using Flexslider Views Slideshow module for creating the sliders.

I edited the file flexslider/flexslider_views_slideshow/js/flexslider_views_slideshow.js in this file you can find all the current options, I added the after callback. In that file there is a variable called fullId which can be used to know which code to add to each slider:

...
          manualControls:settings.manualcontrols,
          start: function(slider) {
            flexslider_views_slideshow_register(fullId, slider);
          },
	  after: function(slider){
		 if(fullId == "#slider1"){
		    // some code
		 }
		 else{
		   // other code
		 }
	  }
...

this worked for me very well,

hope this can help you,

Eduardo

wiktorb’s picture

I made a patch which adds callbacks settings to optionset.

minorOffense’s picture

Status: Postponed » Needs review
Dentorat’s picture

Has there been any update to this? I tried running the patch in #7, which gave me the options in the drupal interface, but as far as I could tell, they didn't actually work

minorOffense’s picture

Status: Needs review » Closed (won't fix)

We can't add the callbacks to the UI. The function drupal_json_encode takes any javascript and converts it to a string value. Which means the browser won't treat the text as "code" and you'll get errors.

If you want to use the callbacks, you'll have to use the library the old fashioned way. I'm keeping my eye on a module which offers a replacement for the default drupal_json_encode function which allows "code" text to be sent, but it's got some show-stopping issues at the moment.

Novascreen’s picture

Why don't you forward the events to the dom container so one can delegate multiple event handlers to it from anywhere?

I changed my flexslider.load.js in this way:

var optionset = settings.flexslider.optionsets[settings.flexslider.instances[id]];

to

var optionset = settings.flexslider.optionsets[settings.flexslider.instances[id]];
optionset = $.extend(optionset || {}, {
  before: function(slider) {
    slider.trigger('before');
  },
  after: function(slider) {
    slider.trigger('after');
  }
});

and then use:

$('.flexslider').on('after', function () {
}

You could also add the flexslider object as parameter.

I know this might not be the best implementation on my side, but i think you get the idea.

yang_yi_cn’s picture

Status: Closed (won't fix) » Active

I think a configurable UI might be too complicated, but #11 is a good solution for anyone want to implement it in code.

Can we get it committed?

yang_yi_cn’s picture

FileSize
910 bytes

convert #11 to a patch

minorOffense’s picture

Status: Active » Needs work

There's no means of rendering the js from a text area in drupal to the browser (filters automatically kill that option).

But I do want to implement something like what you've done in that patch. Reading this post from lullabot http://www.lullabot.com/articles/your-javascript-should-expose-apis-too I just need time/feedback on which technique would work best.

Btw, I don't think we can use the .on method with jquery 1.4.4. But I could be wrong.

yang_yi_cn’s picture

it looks like you can catch the event using .on() after jQuery 1.7 (that's the way the official jQuery doc uses), but before that you can use .bind() to catch an event (that's the way done in the lullabot article).

In both case the event can be send by .trigger(), so I don't think it's a problem to put the trigger function in here, it's added since jQuery 1.0 with the ability to trigger default javascript events, and in 1.3 you can trigger custom events.

rooby’s picture

Title: Can a callback function be added to the flexslider options? » Allow the use of the flexslider callback functions?
Category: support » feature

We can't add the callbacks to the UI. The function drupal_json_encode takes any javascript and converts it to a string value. Which means the browser won't treat the text as "code" and you'll get errors.

The views slideshow cycle module allows you to enter js code for callbacks via the slideshow display setting in the views configuration. - However I believe it only lets you add, not edit, so to edit a snippet you have to remove it and re-enter it.

Having said that, I am also not a fan of the idea of entering code snippets into the database via the UI.
It introduces a possible world of pain.

I would love a solution where I can just integrate via javascript in a module or theme, either like #13 or like #14.

rooby’s picture

Status: Needs work » Needs review
FileSize
2.47 KB

New version of patch in #13.

Also supports the views slideshow implementation.

Use bind() instead of on() with the default drupal jQuery, as mentioned in #14.

DaneMacaulay’s picture

rooby, exactly what i was thinking.
agree with minorOffense, providing events to act on makes this easily extensible.
keep js out of text inputs.

maybe the events should be more uniquely identified though, a preface of "flexslider_" ought to do the job

Anonymous’s picture

I've implemented the patch from #17, working great!

gooddesignusa’s picture

Any chance this patch could be re-rolled for 7.x-2.x-dev version. Thanks in advance

chefnelone’s picture

I'm also looking for this patch for version 7.x-2.
@gooddesignusa: did you find a way to get this working?

gooddesignusa’s picture

@chefnelone
I actually got this working manually. Since the patch didn't apply. I didn't create a patch because I didn't have enough time to test to make sure it added the callback to every scenario.

If you want to look over the changes and make a patch / test feel free.
This is what my flexslider.load.js looks like

(function ($) {

// Behavior to load FlexSlider
Drupal.behaviors.flexslider = {
  attach: function(context, settings) {
    var sliders = [];

    for (id in settings.flexslider.instances) {
      
      if (settings.flexslider.optionsets[settings.flexslider.instances[id]] !== undefined) {
        if (settings.flexslider.optionsets[settings.flexslider.instances[id]].asNavFor !== '') {
          // We have to initialize all the sliders which are "asNavFor" first.
          _flexslider_init(id, settings.flexslider.optionsets[settings.flexslider.instances[id]], context, settings);
        }
        else {
          // Everyone else is second
          sliders[id] = settings.flexslider.optionsets[settings.flexslider.instances[id]];
        }
      }
    }
    // Slider set
    for (id in sliders) {
      _flexslider_init(id, settings.flexslider.optionsets[settings.flexslider.instances[id]], context, settings);
    }
  }
};

/**
 * Initialize the flexslider instance
 */
function _flexslider_init(id, optionset, context, settings) {
  $('#' + id, context).once('flexslider', function() {
    // Remove width/height attributes
    // @todo load the css path from the settings
    $(this).find('ul.slides > li > img').removeAttr('height');
    $(this).find('ul.slides > li > img').removeAttr('width');
    
    if (optionset) {
      //$(this).flexslider(optionset);
                  // Add events that developers can use to interact.
            $(this).flexslider($.extend(settings.flexslider.optionsets[optionset], {
              start: function(slider) {
                slider.trigger('start');
              },
              before: function(slider) {
                slider.trigger('before');
              },
              after: function(slider) {
                slider.trigger('after');
              },
              end: function(slider) {
                slider.trigger('end');
              },
              added: function(slider) {
                slider.trigger('added');
              },
              removed: function(slider) {
                slider.trigger('removed');
              }
            }));
    }
    else {
      $(this).flexslider();
    }
  });
}

}(jQuery));

Inside my theme script file I was running this code

jQuery(document).ready(function($) {
  $body = $('body');
  if($body.hasClass('front')){
    $('.flexslider').bind('start', function () {
      // add code here //
    });
  }
});
chefnelone’s picture

@gooddesignusa: thanks!
Your code works but all sliders are shown with the Default "option set" even when you select another option set, for instance: "basic carousel". Have you tried using other option set (provided by the example module) than default?

Denis Danielyan’s picture

@23

replace

$(this).flexslider($.extend(settings.flexslider.optionsets[optionset], {

with

$(this).flexslider($.extend(optionset, {

kenorb’s picture

Patch for 7.x-2.0-alpha1, should work also for 7.x-2.x (based on #22 and #24)

If jQuery hooks doesn't work, make sure that flexslider.load.js file is loaded. If not, please add flexslider_add(); into your preprocess function. Also if you're using Views, please make sure that you're using FlexSlider, not Slideshow format.

alexweber’s picture

Patch in #25 works for me, thanks!

kenorb’s picture

Status: Needs review » Reviewed & tested by the community
alexweber’s picture

@kenorb, not that I don't appreciate it, but it might be best to let others review this, setting to RTBC based off of one successful use case might be jumping the gun a bit :)

kenorb’s picture

To summarise:
Patch from #7 has a little different approach as it's adding the settings for callbacks in UI.
Patch #25 is actually based on #17
The only suggestion about this patch is that triggers should use different names at #18

But based on #18, #19, #21, #22, #26 it seems that it was quite heavily tested by community.
So let maintainer decide what to do next.

minorOffense’s picture

Status: Reviewed & tested by the community » Closed (fixed)

Committed to dev.

Thanks for all the great work everyone!

minorOffense’s picture

Version: 7.x-1.x-dev » 7.x-2.x-dev
justinen’s picture

I was looking for a way to utilize callback functions to add some custom functionality to my flexslider created with views and luckily I found this post! The update that was submitted was very helpful, but the only thing it was lacking was the slider object parameter. I saw that in #11, Novascreen said "You could also add the flexslider object as parameter.", but this was never actually added to the update.

Unless I'm missing something, this is very important if you want to be able to customize the slider.

In \assets\js\flexslider.load.js under "_flexslider_init", I added the "slider" object as an optional parameter in the trigger function. Feel free to patch this if you think it's valuable to include.

if (optionset) {
// Add events that developers can use to interact.
$(this).flexslider($.extend(optionset, {
start: function(slider) {
slider.trigger('start', [slider]);
},
before: function(slider) {
slider.trigger('before', [slider]);
},
after: function(slider) {
slider.trigger('after', [slider]);
},
end: function(slider) {
slider.trigger('end', [slider]);
},
added: function(slider) {
slider.trigger('added', [slider]);
},
removed: function(slider) {
slider.trigger('removed', [slider]);
}
}));

l0calh0rst’s picture

@justinen: I second that. Was looking for the same thing.

To properly catch that event with the slider (adding an optionial pause here):

$('.flexslider').bind('end', function(event, slider) {
  slider.pause();
  setTimeout(function(){
    slider.play();
  }, 1000);
});
rooby’s picture

If you have something valuable to add please open a new issue and suply a patch file.

hkirsman’s picture

So how do you access the slider if it's not passed as a parameter in the callback? I think this issue is half-way done.

For example it's quite easy to make tabindex work if there would be slider object:

jQuery('.flexslider').bind('start', function(e, slider) {
  slider.slides.eq(slider.currentSlide).siblings().find('a').attr('tabindex', '-1');
});

jQuery('.flexslider').bind('after', function(e, slider) {
  slider.slides.find('a').attr('z-index', '');
  slider.slides.eq(slider.currentSlide).siblings().find('a').attr('tabindex', '-1');
});

Proposed solution #32 from justinen works.

hkirsman’s picture

Issue summary: View changes
Status: Closed (fixed) » Needs work
JuliaKoelsch’s picture

I agree that the object is very helpful to include in the callback. I needed the currentSlide value so that I could apply additional css to elements outside of the slider.

I have created a patch of the code supplied in #32.

alexweber’s picture

Status: Needs work » Needs review

Patch looks fine to me!

emanaton’s picture

Re-rolling patch from comment 37 to be compatible with make-file inclusions.

jonathan_hunt’s picture

Re-roll to add missing init() callback.

DamienMcKenna’s picture

The patch in #40 seems to work.

JuliaKoelsch’s picture

The latest patch in #40 works for me as well. Thanks!

sokrplare’s picture

Status: Needs review » Reviewed & tested by the community
couloir007’s picture

I have applied the patch and used this piece of code just to see if I can get it right.

$('.flexslider').bind('start', function(e, slider) {
	slider.pause();
});

I am unable to get callbacks working. Is there something else that I am missing?

Thank you.

couloir007’s picture

I realized I had the code located where is was running before flexslider had initialized.

ada05’s picture

@couloir007 how did you solve it? where did you place the code?

couloir007’s picture

@ada05, I put it in a Drupal.behaviors function. Similar to what is below.

Drupal.behaviors.flexslider = {
    attach: function (context, settings) {   
        $('.flexslider').bind('start', function(e, slider) {
            $('.flex-control-thumbs li:first-child').addClass('active');			
        });
    }
};
bneil’s picture

The patch in #40 works well for me.

minax.de’s picture

As the additional patch for passing the slider object into the event handler is not yet committed, a possible workaround would be:
var slider = $(this).data('flexslider'); as documented here: https://github.com/woothemes/FlexSlider#general-notes.

maadis.ie’s picture

Hi,

I have stalled flexslider module 7.x-2.0-rc1 with flexslider library 2.6, and slideshow is working fine. My slide is normal - photos on image and messages/captions on body field - and I have shown body field on top of the image on transparent. I would like to give sliding and delay effect on messages/captions after the actual image goes on the slide. I have been trying to use start, before and after callback functions, like:

$('.slider').flexslider({
    animation: "slide",
    controlNav: false,
    animationLoop: false,
    start:function(){},
    before: function(){},
    after: function(){
        
    },

   ....
    ...
})

Trying all possible combinations did not work, and now I saw this link. Do I have to apply the patch? The version I am using is 7.x-2.0-rc1. I am trying to give delay and sliding effect of the message of active slide (.flex-active-slide) using after() callback.
I appreciate if you could give me some pointers how I go about this.

Thanks, Maadis

adam1’s picture

I read this thread but in the end I didn't know what steps to go to implement the functionality I wrote below. (At the moment I am using flexslider 2.0-rc1). Would be glad if someone could list the steps.

 $('#main-slider').flexslider({
    animation: "slide",
    start: function(){
         $(".flex-prev").css("top","70px");
         $(".flex-next").css("top","70px");
    }
  });
bneil’s picture

@adam1:

Use the reference in #48 to bind to the start method via the Drupal Behaviors functionality. You will need to add this to a javascript file that a custom module or your theme is loading.

jwilson3’s picture

Just chiming in to say this issue was the first thing that popped up in my Google search for how to alter a flexslider only after it loads and modifies its own dom structure.

couloir007's post in #48 is the perfect solution. Thanks to all who worked on getting this in.

adam1’s picture

@bneil thank you!

minorOffense’s picture

Status: Reviewed & tested by the community » Fixed

Patch applied. Thanks a lot for the hard work!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

thronedigital’s picture

gvso’s picture

I followed #48 and I'm unable to make it work.

(function ($) {
 
  Drupal.behaviors.flexslider = {
    attach: function (context, settings) {   
        $('.flexslider').bind('start', function(e, slider) {
          console.log('test');			
        });
    }
  };
  
}(jQuery));

This doesn't work. I'm using views_slideshow_flexslider. Can that be the reason?

TheGentleman’s picture

So I'm trying to use the flexslider callback function but nothing seems to be triggering. What I'm trying to do is make a callback to my slideshow and trigger a function after each slide change. My google search brought me here. I'm just trying to trigger a console log to make sure it is even triggering after every slide change. This is what I have in my javascript file

$(document).ready(function() {

$('.flexslider').flexslider({

    animation: "slide",
    start: function(){
        console.log('Slideshow start');
    },
    before: function(){
        console.log('Before slide');
    },
    after: function(){
        console.log('after slide');
    },
    animationLoop: false
});


});

nothing is coming up in my log. I'm sure there's something simple i'm mising but I don't know what it is. I tried #48 solution but nothing is happening either. HELP!

hkirsman’s picture

And you applied the patch?

lbrassaw’s picture

You don't have to apply the patch anymore. It's been applied. Use:

(function($){

     Drupal.behaviors.my_custom_flexslider_behaviour = {
          attach: function (context, settings) {   
               $('.flexslider').bind('start', function(e, slider) {
                    console.log('test start');
               });
               $('.flexslider').bind('before', function(e, slider) {
                    console.log('test before');
               });
               $('.flexslider').bind('end', function(e, slider) {
                    console.log('test end');
               });
          }
     };

})(jQuery);

Thanks all for the hard work over the years. ;)

randell’s picture

Tested #63 to work on 7.x-2.0-rc2.

thetwentyseven’s picture

I have the version 7.x-2.0-rc2 and using the #63 code. It is not working for me.

(function ($) {
  Drupal.behaviors.myModuleBehavior = {
    attach: function (context, settings) {
      console.log('test js');
      console.log($('.flexslider'));
      $('.flexslider').bind('start', function(e, slider) {
        console.log('test start');
      });
      $('.flexslider').bind('before', function(e, slider) {
        console.log('test before');
      });
      $('.flexslider').bind('end', function(e, slider) {
        console.log('test end');
      });

    }

  };
})(jQuery);

I can see 'test js' in my console but not the rest. What could be happening? I also tried with a different scope and weight in drupal_add_js. I cleared cache, and advagg too just in case. Any ideas?

Solution: The problem was that I was using flexslider with a view which use the module https://www.drupal.org/project/flexslider_views_slideshow. Therefore I had to apply another patch for that module #2149779: Allow the use of the flexslider callback functions?