Hi I found a solution to implement collapsible block with JQuery. I found the tip at Here the Author defined from the site is keven.squad5.

Well I did implement the code and is ok! the only bug is that it hide automatic any block settled on left or right sidebar, With Firebug you can deactivate the inserted css tag element style {display:none;} and show the block again.

What happen is that there is no Show/Hide (Block Title) link for switching from hide/show. Below the code:

1. Blocks.toggle.js

function toggle_block(id, target_id){
$("#"+id).click(function() {if($.cookie(target_id) != 'shown'){
$("#"+target_id).show('slow');
$.cookie(target_id, 'shown');
}else{
$("#"+target_id).hide('slow');
$.cookie(target_id, 'hidden');
}
});

if($.cookie(target_id) != 'shown'){
$('#'+target_id).hide();
}
}

2. block.tpl.php:


<?php // $Id: block.tpl.php,v 1.3 2007/08/07 08:39:36 goba Exp $

drupal_add_js(path_to_theme() . '/js/jquery.cookie.js');
drupal_add_js(path_to_theme() . '/js/blocks.toggle.js');
$js = '$(document).ready(function(){' . ' toggle_block(\'toggle-' . $block->module .'-'. $block->delta . '\', \'block-' . $block->module .'-'. $block->delta . '\');' .'});';
drupal_add_js($js,'inline');
?>

<div id="block-<?php print $block->module .'-'. $block->delta; ?>" class="clear-block block block-<?php print $block->module ?>">
<?php if (!empty($block->subject)): ?>
  <h2><a href="#" id="toggle-<?php print $block->module .'-'. $block->delta ?>"><?php print $block->subject ?></a></h2>
<?php endif;?>
   <div class="block-content" id="block-<?php print $block->module .'-'. $block->delta; ?>"><?php print $block->content ?>
   </div>
</div>

Any help is very much appreciate I'm not a coder :-) Thanks

Comments

vm’s picture

Wolfflow’s picture

Thanks @VM I know that module, just building a solution for only one page.tpl.php as not to have to much modules installed.

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

seutje’s picture

preprocess_block:

function [THEME OR MODULE NAME]_preprocess_block(&$vars) {
  $block = $vars['block'];
  if (/* condition for activating, e.g. $block->module == 'foo' or by path or something */) {
    drupal_add_js(path_to_theme() . '/js/jquery.cookie.js');
    drupal_add_js(path_to_theme() . '/js/blocks.toggle.js');
    $settings = array(
      'toggleblock' = array(
        'block-' . $block->module . '-' . $block->delta,
      ),
    );
    drupal_add_js($settings, 'setting');
  }
}

blocks.toggle.js:

// your everyday closure
(function($) {
  // put this behavior in the "toggleblock" namespace
  Drupal.behaviors.toggleblock = function(context) {
    // Set the link for the text early on so we only run it once
    var linktext = Drupal.t('Show/hide');
    // iterate over the toggleblock settings array
    $.each(Drupal.settings.toggleblock, function(i, elId) {
      // select the element that matches the ID, excluding already
      // processed ones and those that aren't in the current context
      // the each here is just to nulify things when there are no results
      $('#' + elId + ':not(.toggleblock-processed)', context).each(function() {
        // set the cookie variable as a boolean for this particular one
        // if it isn't set, it'll default to showing the block
        // would prolly be easier to work with booleans instead of
        // 'shown' and 'hidden'
        var cookie = $.cookie(elId) != 'hidden',
              $this = $(this);
        // construct the link
        $('<a href="#" class="toggleblock-link">')
        // add the previously cached linktext
        .text(linktext)
        // bind a click handler
        .bind('click', function() {
          // cache some things we might need
          var $this = $(this),
                $block = $this.parent(),
                $content = $block.children('.content'),
                collapsed = $block.hasClass('collapsed');
          // stop the current animation, force it to its end point and
          // toggle its display, setting a collapsed class and
          // the cookie on the callback
          $content.stop(true).toggle('slow', function() {
            $block.toggleClass('collapsed');
            $.cookie($block.attr('id'), collapsed ? 'shown' : 'hidden');
          });
          return false;
        })
        // add it to the block, right before the title
        // (or right before the content if there is no title)
        .prependTo($this);
        // match this block's state with the cookie
        if (!cookie) {
          $this.hide().addClass('collapsed');
        }
      });
    });
  }
})(jQuery);
Wolfflow’s picture

@seutje : will give it a go, thanks meanwhile!!

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

Wolfflow’s picture

@seutje

done this:

function garland_preprocess_block(&$vars) {

but unclear for this:

(/* condition for activating, e.g. $block->module == 'foo' or by path or something */)

I would like to have it activated for every block when user have permission to hide/diplay blocks

Should I put the _preprocess_ function in the garland template.php or only in my block.tpl.php?

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

seutje’s picture

preprocess implementations go in template.php

if (user_access('hide/display blocks')) I suppose, assuming this permission is defined by something in a hook_perm implementation

Wolfflow’s picture

Success! Really many thanks @seutje , appreciate and thankful for the time you dedicate to drive me in the right direction.
I spent really many times to look for a simple implementation, that can very easy be customize now.

One note on my code, that you missed also in your preprocess_block: suggestion, there was a small bug:

toggleblock' = array(

should be like this:

toggleblock' => array(

IMHO: With this small solution every one wants avoid to install collapsiblock and required Javascript Tools will have more choice for installing other very usefully contributed modules.

Again thanks I own you a beer!!
Regards

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

Wolfflow’s picture

Hi @sutje, just as additional information, could you please direct me where should the hook_permission be inserted?

A. After the function in the theme template.php file
B. By building a small module suppose it should go in the collapsyblockcookie.module
C. or in a collapsyblockcookie.admin.inc

Regards

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

seutje’s picture

hmm, yea sry, I never actually tested it, I just wrote that as an example or startingpoint

unfortunately, themes can't implement hook_permission in Drupal 6 (they can in 7 so then you can just drop it in template.php), so you'll have to make it into a module and then you might as well move the js and preprocess_block implementation to that same module

Wolfflow’s picture

Required code for implementing:

A template file to create in your theme folder
block.tpl.php
<?php
// $Id: block.tpl.php,v 1.3 2007/08/07 08:39:36 goba Exp $
?>
<div id="block-<?php print $block->module .'-'. $block->delta; ?>" class="clear-block block block-<?php print $block->module ?>">

<?php if (!empty($block->subject)): ?>
  <h2><?php print $block->subject ?></h2>
<?php endif;?>

  <div class="content"><?php print $block->content ?></div>
</div>
A JavaScript to put in your theme /js folder
blocks.toggle.js
// your everyday closure
(function($) {
  // put this behavior in the "toggleblock" namespace
  Drupal.behaviors.toggleblock = function(context) {
    // Set the link for the text early on so we only run it once
    var linktext = Drupal.t('Show/Hide');
    // iterate over the toggleblock settings array
    $.each(Drupal.settings.toggleblock, function(i, elId) {
      // select the element that matches the ID, excluding already
      // processed ones and those that aren't in the current context
      // the each here is just to nulify things when there are no results
      $('#' + elId + ':not(.toggleblock-processed)', context).each(function() {
        // set the cookie variable as a boolean for this particular one
        // if it isn't set, it'll default to showing the block
        // would prolly be easier to work with booleans instead of
        // 'shown' and 'hidden'
        var cookie = $.cookie(elId) != 'hidden',
              $this = $(this);
        // construct the link
        $('<a href="#" class="toggleblock-link">')
        // add the previously cached linktext
        .text(linktext)
        // bind a click handler
        .bind('click', function() {
          // cache some things we might need
          var $this = $(this),
                $block = $this.parent(),
                $content = $block.children('.content'),
                collapsed = $block.hasClass('collapsed');
          // stop the current animation, force it to its end point and
          // toggle its display, setting a collapsed class and
          // the cookie on the callback
          $content.stop(true).toggle('slow', function() {
            $block.toggleClass('collapsed');
            $.cookie($block.attr('id'), collapsed ? 'shown' : 'hidden');
          });
          return false;
        })
        // add it to the block, right before the title
        // (or right before the content if there is no title)
        .prependTo($this);
        // match this block's state with the cookie
        if (!cookie) {
          $this.hide().addClass('collapsed');
        }
      });
    });
  }
})(jQuery);
A preprocess function to add in your theme template.php file
Code to add in template.php
<?php
function garland_preprocess_block(&$vars) {
  $block = $vars['block'];
  if (user_access('content')) {
    drupal_add_js(path_to_theme() . '/js/jquery.cookie.js');
    drupal_add_js(path_to_theme() . '/js/blocks.toggle.js');
    $settings = array(
      'toggleblock' => array(
        'block-' . $block->module . '-' . $block->delta,
      ),
    );
    drupal_add_js($settings, 'setting');
  }
}
?>
The jQuery file
You can download the file at: COOKIE, the jQuery Plugin page.

Note: The code works but still have some buggy behave:

1. After some testing Show/Hide Block , the block/s disappear. it look that a settings conflict exist.

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

Wolfflow’s picture

FYI:

As I'm not expert in licence matter I have sent an email to the original Author of the code for asking for collaboration and permission.
For correctness I post here the email text:


Hi Keven, I picked up the code you build for - JQuery Collapsible Block with Cookies - after finding your page http://keven.squad5.net/book/export/html/20
I found it a great idea and started to test. With the help of the Drupal.org community we managed to reach a first running solution.
You may find additional documentation at http://drupal.org/node/845194.
I would wery much appreciate if you may chip in and give your feedback. I will provide a snipset page on Drupal.org when it's ready. Of course I write to you also for asking your permission.
Thanks meanwhile for sharing.
Regards
Wolf Zirbs (alias Wolfflow)

sent to http://keven.squad5.net/ with sites contact form 07.07.2010 10:30

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

blueflowers’s picture

This is Keven Ages here. You absolutely have my persmission and blessing to do whatever you'd like with this code Wolfflow. I'm glad you find it useful!

Wolfflow’s picture

Work in progress:

/**
 * Implementation of hook_perm().
 */
function collapsiblock_perm() {
  return array(
     'administer collapsiblock'
     'access collapsiblock'
);

}

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

blueflowers’s picture

Here is the correct way to implement block.tpl.php

<div id="block-<?php print $block->module .'-'. $block->delta; ?>" class="clear-block block block-<?php print $block->module ?>">

<?php if (!empty($block->subject)): ?>

<h2><a href="#" id="toggle-<?php print $block->module .'-'. $block->delta ?>"><?php print $block->subject ?></a></h2>

<?php endif;?>

<div class="block-content" id="block-<?php print $block->module .'-'. $block->delta; ?>">

<?php print $block->content ?>

</div>



</div>
Wolfflow’s picture

FYI Demonstration Site:

For those that would like to see how this small project works at actual development stage you can visit Drupal 6.17 Sandbox Site,
please use --- user: demo and password: demo --- to log in.

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

volocuga’s picture

So assuming the code above isn't working. I tried to get it working with rootcandy theme and faced the same bug as discribed by Wolfflow - after show/hide link clicked, this block disappeared for ever.

Any ideas how to fix it?

Wolfflow’s picture

Hi @volocuga. I am trying to build a small module for this but as I'm not a php proof it will take me some time to figue this out. Stay tuned.
Regards

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

blueflowers’s picture

What does your block.tpl.php code look like?

Wolfflow’s picture

Hi, Keven, glad to get your support and thanks for granted permission in name of me and others who may find this useful.

So the code of block.tpl.php is as follow:

<?php
// $Id: block.tpl.php,v 1.3 2007/08/07 08:39:36 goba Exp $
?>
<div id="block-<?php print $block->module .'-'. $block->delta; ?>" class="clear-block block block-<?php print $block->module ?>">

<?php if (!empty($block->subject)): ?>
  <h2><?php print $block->subject ?></h2>
<?php endif;?>

  <div class="content"><?php print $block->content ?></div>
</div>

Kind Regards

Note: I just re-paste here the code edited at #Update comment above.

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

blueflowers’s picture

Replace your current block.tpl.php code with the following:

<div id="block-<?php print $block->module .'-'. $block->delta; ?>" class="clear-block block block-<?php print $block->module ?>">

<?php if (!empty($block->subject)): ?>

<h2><a href="#" id="toggle-<?php print $block->module .'-'. $block->delta ?>"><?php print $block->subject ?></a></h2>

<?php endif;?>

<div class="block-content" id="block-<?php print $block->module .'-'. $block->delta; ?>">

<?php print $block->content ?>

</div>



</div>
Wolfflow’s picture

@blueflowers - nope.

(unstable) - last used from me:

<div id="block-<?php print $block->module .'-'. $block->delta; ?>" class="clear-block block block-<?php print $block->module ?>">

<?php if (!empty($block->subject)): ?>
  <p><h2 class="fieldset-title"><?php print $block->subject ?></h2></p>
      <?php else: ($block->subject) ?>
		<p><h2 class="fieldset-title"><?php print '<hr></hr>'; ?></h2></p>
  <?php endif;?>

  <div class="content"><p><?php print $block->content ?></p></div>
</div>

I think the problems lies that we need a substitute/replace "hide"-link that may call the javascript toggle for status=visible
and then when clicked for set status=invisible the javascript call a substitute/routine for showing the "display"-link.

I will try to separate/divide the toggle js code, 1. for hiding, 2. for displaying

...to be continued

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

Wolfflow’s picture

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

Wolfflow’s picture

I think we should find another approach with JQuery Collapsible Block with Cookies
I did a bit of searching and with your help we should be better off with

JQuery Toggle-block with Cookies

So I have found some help (here) Simple Toggle with CSS & jQuery

The code parts that should be modified for working in Drupal with Jquery are:

  1. Code for inserting the jquery-toggle themename_preprocess_function in the template.php file
    function themename_preprocess_block(&$vars) {
      $block = $vars['block'];
      if (user_access('access content')) {
        drupal_add_js(path_to_theme() . '/js/toggle.js');
        $settings = array(
          'toggleblock' => array(
            'block-' . $block->module . '-' . $block->delta,
          ),
        );
        drupal_add_js($settings, 'setting');
      }
    }
    
  2. the to trasform toggle.js file
    function rC(nam) {
      var tC = document.cookie.split('; '); 
        for (var i = tC.length - 1; i >= 0; i--) {var x = tC[i].split('='); 
         if (nam = x[0]) return unescape(x[1]);} return '0';
    } 
    
    function wC(nam,val,expires) { 
          if (!expires) expires = new Date(); 
           expires.setDate(expires.getDate()+1); 
             document.cookie = nam + '=' + escape(val)+ '; 
               expires='+ expires.toGMTString()+ '; path=/';
    } 
    
    function thisPage() {
      var page = location.href.substring(location.href.lastIndexOf('\/')+1); 
        pos = page.indexOf('.');
          if (pos > -1) {page = page.substr(0,pos);
    
    } 
    return page;
    
    } 
    
    function toggle(nam,expires) {var val = rC(nam); 
      if (val=='1') {wC(nam,'0',expires); 
       return false;} wC(nam,'1',expires); return true;
    }
    
    // Drupal behavior toggleblock
    
    var expires = 0;
    // note that by default the script saves the cookie for one day
    // if you wish to keep the cookie for a longer or shorter period then
    // set the expires variable to the required expiry date instead of 0.
    
    (function($) {
      // put this behavior in the "toggleblock" namespace
      Drupal.behaviors.toggleblock = function(context) {
        // Set the link for the text early on so we only run it once
        var linktext = Drupal.t('Show/Hide');
        // iterate over the toggleblock settings array
        $.each(Drupal.settings.toggleblock, function(i, elId) {
          // select the element that matches the ID, excluding already
          // processed ones and those that aren't in the current context
          // the each here is just to nulify things when there are no results
          $('#' + elId + ':not(.toggleblock-processed)', context).each(function() {
            // set the cookie variable as a boolean for this particular one
            // if it isn't set, it'll default to showing the block
            // would prolly be easier to work with booleans instead of
            // 'shown' and 'hidden'
            var cookie = $.cookie(elId) != 'hidden',
                  $this = $(this);
            // construct the link
            $('<a href="#" class="toggleblock-link">')
            // add the previously cached linktext
            .text(linktext)
            // bind a click handler
            .bind('click', function() {
              // cache some things we might need
              var $this = $(this),
                    $block = $this.parent(),
                    $content = $block.children('.content'),
                    collapsed = $block.hasClass('collapsed');
              // stop the current animation, force it to its end point and
              // toggle its display, setting a collapsed class and
              // the cookie on the callback
              $content.stop(true).toggle('slow', function() {
                $block.toggleClass('collapsed');
                $.cookie($block.attr('id'), collapsed ? 'shown' : 'hidden');
              });
              return false;
            })
            // add it to the block, right before the title
            // (or right before the content if there is no title)
            .prependTo($this);
            // match this block's state with the cookie
            if (!cookie) {
              $this.hide().addClass('collapsed');
            }
          });
        });
      }
    })(jQuery);
    
    window.onload = start;
    
  3. This JQuery code must be implemented some-where
    $(document).ready(function(){
    
    	//Hide (Collapse) the toggle containers on load
    	$(".toggle_container").hide(); 
    
    	//Switch the "Open" and "Close" state per click then slide up/down (depending on open/close state)
    	$("h2.trigger").click(function(){
    		$(this).toggleClass("active").next().slideToggle("slow");
    	});
    
    });
    

This is a development tryout, so it does not work now, I'm just guessing.
Authors of relative codes are being contacted

Contact me for drupal projects in English, German, Italian, Drupal Hosting Support.

gagarine’s picture

I'm the maintainer of http://drupal.org/project/collapsiblock. I sugest if you want the same feature as collapsiblock but not want to use a module you should check the JS inside. It was tested by thousands of poeple without major problem.

But if I was you I will just grab the module.... is very light and works out-of-the-box.

https://interface-network.com - Interface Network is an action and research technology governance agency.