In drupal i have generated a list where each item is a fieldset with collapsible, that can contain extra information.
Because of the rather large list i want to avoid loading the extra information until a user clicks on the fieldset.
Best case scenario:
User clicks on collapsed fieldset.
Fieldset loads extra information.
Fieldset uncollapses.
I’ve copied and loaded the copy of collapse.js into my form, but I’m very new to js and jQuery, so I’m a little lost. If someone can show me how to call a function the first time the fieldset is expanded, I’m sure i can figure out the rest.
I’ve included the code from collapse.js:
(function ($) {
//Toggle the visibility of a fieldset using smooth animations.
Drupal.toggleFieldset = function (fieldset) {
var $fieldset = $(fieldset);
if ($fieldset.is('.collapsed')) {
var $content = $('> .fieldset-wrapper', fieldset).hide();
$fieldset
.removeClass('collapsed')
.trigger({ type: 'collapsed', value: false })
.find('> legend span.fieldset-legend-prefix').html(Drupal.t('Hide'));
$content.slideDown({
duration: 'fast',
easing: 'linear',
complete: function () {
Drupal.collapseScrollIntoView(fieldset);
fieldset.animating = false;
},
step: function () {
// Scroll the fieldset into view.
Drupal.collapseScrollIntoView(fieldset);
}
});
}
else {
$fieldset.trigger({ type: 'collapsed', value: true });
$('> .fieldset-wrapper', fieldset).slideUp('fast', function () {
$fieldset
.addClass('collapsed')
.find('> legend span.fieldset-legend-prefix').html(Drupal.t('Show'));
fieldset.animating = false;
});
}
};
//Scroll a given fieldset into view as much as possible.
Drupal.collapseScrollIntoView = function (node) {
var h = document.documentElement.clientHeight || document.body.clientHeight || 0;
var offset = document.documentElement.scrollTop || document.body.scrollTop || 0;
var posY = $(node).offset().top;
var fudge = 55;
if (posY + node.offsetHeight + fudge > h + offset) {
if (node.offsetHeight > h) {
window.scrollTo(0, posY);
}
else {
window.scrollTo(0, posY + node.offsetHeight - h + fudge);
}
}
};
Drupal.behaviors.collapse = {
attach: function (context, settings) {
$('fieldset.collapsible', context).once('collapse', function () {
var $fieldset = $(this);
// Expand fieldset if there are errors inside, or if it contains an
// element that is targeted by the uri fragment identifier.
var anchor = location.hash && location.hash != '#' ? ', ' + location.hash : '';
if ($('.error' + anchor, $fieldset).length) {
$fieldset.removeClass('collapsed');
}
var summary = $('<span class="summary"></span>');
$fieldset.
bind('summaryUpdated', function () {
var text = $.trim($fieldset.drupalGetSummary());
summary.html(text ? ' (' + text + ')' : '');
})
.trigger('summaryUpdated');
// Turn the legend into a clickable link, but retain span.fieldset-legend
// for CSS positioning.
var $legend = $('> legend .fieldset-legend', this);
$('<span class="fieldset-legend-prefix element-invisible"></span>')
.append($fieldset.hasClass('collapsed') ? Drupal.t('Show') : Drupal.t('Hide'))
.prependTo($legend)
.after(' ');
// .wrapInner() does not retain bound events.
var $link = $('<a class="fieldset-title" href="#"></a>')
.prepend($legend.contents())
.appendTo($legend)
.click(function () {
var fieldset = $fieldset.get(0);
// Don't animate multiple times.
if (!fieldset.animating) {
fieldset.animating = true;
Drupal.toggleFieldset(fieldset);
}
return false;
});
$legend.append(summary);
});
}
};
})(jQuery);
It looks to me like you’d have to override the whole
Drupal.toggleFieldsetfunction (just like when you are overriding a Drupal theme function.You could perhaps add a class to the fieldset in FormAPI then catch it in the
completefunction of the$content.slideDownparams and fire a custom function of yours, to add a ‘loading’ graphic and make your ajax request.I’m assuming from your question that you are familiar enough with FormAPI/jQuery.ajax() to have a go. But let me know if not and i’ll include some snippets
EDIT
Here is some example code, it’d take a quite a while to setup a test environment for this, so it’just a pointer (cant create a JS fiddle for this ;))
You might add your fieldset like this in PHP
You’ll also obviously have setup a menu hook returning your themed data @ callback/url/path. IMO it’s better to return JSON data and theme them in with JS templating, but the Drupal way (for the moment at least) seems to be to render HTML in the menu hook callback function.
Then here is the JS. I’ve only included the altered complete function, rather than reproduce what you pasted. Add the complete function in to a copy of the code the re-specify the core Drupal function in your own JS file
Or, rather than messing around with the collapsible function. just create your own fieldset without the collapsible/collapsed classes and implement from scratch yourself
….so.. something like that 🙂