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?

Files: 

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

StatusFileSize
new3.32 KB
Test request sent.
[ View ]

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

StatusFileSize
new910 bytes
Test request sent.
[ View ]

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
StatusFileSize
new2.47 KB
Test request sent.
[ View ]

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

rsmylski’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

StatusFileSize
new1.01 KB
Test request sent.
[ View ]

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
Spry_Julia’s picture

StatusFileSize
new1.33 KB
Test request sent.
[ View ]

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

StatusFileSize
new1.13 KB
Test request sent.
[ View ]

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

jonathan_hunt’s picture

StatusFileSize
new1.22 KB
Test request sent.
[ View ]

Re-roll to add missing init() callback.

DamienMcKenna’s picture

The patch in #40 seems to work.

Spry_Julia’s picture

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

covenantd’s picture

Status:Needs review» Reviewed & tested by the community