Yii 1.1: slidetoggle

Make containers collapsible (fieldset,portlet,div,ul ...)
22 followers

Make any containers collapsible (fieldset,portlet,div,ul ...). The lightweight extension uses the jQuery function 'slideToggle' to collapse/expand the containers. An arrow will be added to the title of the container by default, but you can switch off this feature.

Note:

  • If you update to v1.1.2 don't forget to delete the published assets.

Requirements

Should work with Yii 1.1 or above

Usage

  • extract the files under .../protected/extensions

In the Yii blog demo add this code at the top of views/post/index.php

<?php
$this->widget('ext.slidetoggle.ESlidetoggle',
  array(
   'itemSelector' => 'div.post',
   'titleSelector' => 'div.post .title',
   'collapsed' => 'div.post',
  ));
?>

All posts should appear collapsible now, collapsed by default.

Details

The properties

  • itemSelector (container)
  • titleSelector (title to click)
  • collapsed (selector for containers collapsed by default)

have to be assigned as jQuery selector terms.

More options

  • arrow: true/false
  • duration: 'slow','fast' or time in ms
  • easing: 'linear','swing','easeInExpo','easeInSine' ... see jQuery Easing Plugin
  • cssFile: if you want to display a custom arrow. See assets/css/jquery.slidetoggle.css

Note: The title tag must be a child of the container tag.

Example view:

<?php
 
/**
 * 1. Fieldsets
 *
 * Default settings of the widget.
 * This will make all fieldsets in a view collapsible, expanded by default.
 * An arrow will be added to the legend.
 *
 * Note - see HTML:
 * Better to use a single div as wrapper in the fieldset for all elements,
 * otherwise each child element will be toggled separately
 */
 
$this->widget('ext.slidetoggle.ESlidetoggle');
 
 
/**
 * 2. Standard Yii portlets
 * This will make all portlets in a view collapsible, expanded by default.
 */
 
$this->widget('ext.slidetoggle.ESlidetoggle',
array(
    'itemSelector' => '.portlet',
    'titleSelector' => '.portlet-decoration',
    //'collapsed' => '.portlet', //uncomment to show all collapsed
    'arrow' => false, //comment to show the toggle arrow
));
 
 
/**
 * 3. Custom div tags
 *
 * Note - see HTML: 
 * The title must be a child of the collapsible div in the HTML code.
 *
 */
 
$this->widget('ext.slidetoggle.ESlidetoggle',
array(
     'itemSelector' => 'div.collapsible',
     'titleSelector' => 'div.collapsible h3',
     //only the collapsible div container with the class 'closed' is collapsed by default
     'collapsed' => 'div.collapsible.closed', //a subset of the itemSelector
));
 
 
/**
 * 4. Unordered lists
 *
 * Note - see HTML: 
 * Add the title as a child of the ul-tag in the HTML code.
 * Every li-tag will be toggled separately.
 */
 
$this->widget('ext.slidetoggle.ESlidetoggle',
array(
    'itemSelector' => 'ul.collapsible',
    'collapsed' => 'ul.collapsible', //all collapsed
    'titleSelector' => 'ul.collapsible .caption',
));
 
?>
 
<fieldset>
  <legend>The first fieldset</legend>
  <div>
    <label>Input</label>
    <input type="text"/>
    <label>Radio</label>
    <input type="radio"/>
  </div>
</fieldset>
 
<fieldset>
  <legend>The second fieldset</legend>
  <div>
    <label>Input</label>
    <input type="text"/>
    <label>Checbox</label>
    <input type="checkbox"/>
  </div>
</fieldset>
 
<div class="collapsible">
   <h3>Title 1</h3>
   <p>The first collapsible content</p>
</div>
 
<div class="collapsible closed">
   <h3>Title 2</h3>
   <p>The second collapsible content 2</p>
</div>
 
 
<ul class="collapsible">
 <span class="caption" style="margin-left:-1.5em;">Collapsible caption</span>
 <li>Item1</li>
 <li>Item2</li>
 <li>Item3</li>
</ul>

Change the effect of toggle movement by setting the 'duration' and 'easing' property.

$this->widget('mongocms.extensions.slidetoggle.ESlidetoggle',
array(
   'duration' => 'slow', //'fast' or time in ms between 200 and 600
   'easing' => 'swing', //'linear','easeInOutSine','easeInCirc','easeInElastic' ...
));

Notes

  • You can change the image and position of the arrow in jquery.slidetoggle.css, so you can use a [+]/[-] at the right side instead an arrow at the left. Don't forget to delete the assets folder after changing the css file.

  • Values for 'easing': See jQuery Easing Plugin

Change log

  • v1.1 Added jQuery Easing Plugin for more easing methods
  • v1.1.1 Bugfix: removed comma from last options array item in jquery.slidetoggle.js; slidetoggle didn't work in IE
  • v1.1.2
    • Bugfix in css file: Arrow did change background color to transparent;
    • Should work with Yii version < 1.1.6

Resources

Similar extension

Total 13 comments

#11307 report it
__construct() at 2013/01/05 03:54am
Extension doesn't work with Twitter Bootstrap

Hi everyone.

I found a bug in this extension. It doesn't work with Twitter Bootstrap plugin ( http://www.yiiframework.com/extension/bootstrap/ )

In order to solve this problem you shoud rename your javascript function from "collapse" to something else ("eslidetoggle" im my case).

Here is the example:

Wrong code (jquery.slidetoggle.js):

/**
 * jquery.slidetoggle.js
 *
 * Part of Yii extension 'slidetoggle'
 * @author Joe Blocher
 *
 */
jQuery.fn.collapse = function(options) {
 
....
....

Correct code:

/**
 * jquery.slidetoggle.js
 *
 * Part of Yii extension 'slidetoggle'
 * @author Joe Blocher
 *
 */
jQuery.fn.eslidetoggle = function(options) {
// "collapse" function is already defined in Bootstrap
 
....
....

After that you shoud also edit ESlidetoggle.php:

public function registerClientScript()
{
 
....
....
 
$jsOptions =  CJavaScript::encode($options);
$jsCode .= "jQuery('{$this->titleSelector}').eslidetoggle($jsOptions);";

After that everything shoud be alright. Please fix and update the extension.

Thank you!

#7101 report it
DarkNSF at 2012/02/23 03:37pm
Great extension!

Simple to implement

#6427 report it
Sampa at 2012/01/09 07:28pm
Spent some time to realise this...

When I first worked with my portlets I had no problems.

Then I wanted to add the widget on another page aswell, and it actually took me some time before I realised what I was doing wrong.

What didn't work ( only the arrow showed up ):

Bug? Unbalanced unit/spell? Exploit?

If you have detected a bug or any unbalanced unit/spell we would appriciate if you attached a replay in a email to info [at] legiontdpro.com . Please write a short text describing where and when the bug appears, thank you!

How I fixed it:

Bug? Unbalanced unit/spell? Exploit?

If you have detected a bug or any unbalanced unit/spell we would appriciate if you attached a replay in a email to info [at] legiontdpro.com . Please write a short text describing where and when the bug appears, thank you!

I missed a second child element to the selectorItem (in my example

)

#6425 report it
Sampa at 2012/01/09 04:56pm
dont forget about the element:contains("foo") selector of jQuery

this example attaches the widget only to the portlet with "admin" in the portlet decoration (admin is my title..).

'itemSelector' => '.portlet:contains("admin")', 'titleSelector' => '.portlet-decoration:contains("admin")', //'collapsed' => '.portlet:contains("admin")', //uncomment to show all collapsed

#5678 report it
David Dreggors at 2011/10/31 08:23pm
animation issues

I have noticed if I have a smaller div section all of the animations work fine. However, if I have a larger div section (40+ lines of text inside the div) the animation is ignored and the collapse/expand just opens or closes so fast that you cannot even see it.

Example:

I have 3 collapse-able div sections on a page. The first div is a CGridView with 5 rows, inside each of the others is a CDetailView widget with around 40 rows. I populate the widgets with data from the same model/data, just different parts (Work notes history in the CGridView, Contact Info in one CDetailView div and job history in the other).

It is the div sections with the CDetailView widgets in them that the animation is broken in. Since the type of contents in the div should not make a difference I do not think that it is due to 1 being CGridView while the others are CDetailView. I believe this is more directly related to the "amount" of data in the div.

Is this a known issue with jquery (as I am new to jquery and do not know) or something introduced in this extension?

I am willing to test any ideas/solutions you may have since this is a hobby project and just for fun anyway.

#5517 report it
Don Felipe at 2011/10/18 02:06am
@Alex - multiple portlets (collapsed on page load)

I've come across the very same problem this morning as either all my "portals" completely disappeared or the title div was visible but the content wouldn't expand anymore... catch22. After checking the generated source code (the jquery stuff) I figured to rather use unique id's for each portlet (instead of css class names). So...

First, you have to change your portlet's code as follows:

public $model_id = null;
 
public function init()
{
  $this->id='my-portlet-'.$this->model_id;
  $this->decorationCssClass='portlet-decoration-'.$this->model_id;
  //to keep the default class name just append the new class 
  //$this->decorationCssClass='portlet-decoration portlet-decoration-'.$this->model_id;
  //you can do the same here for titleCssClass & contentCssClass but it's not needed for slidetoggle effect
 
  parent::init();
}

Second, you need to pass the (unique) id's to the slidetoggle widget:

$this->widget('ext.slidetoggle.ESlidetoggle', array(
  'itemSelector' => '#my-portlet-'.$model->id,
  'titleSelector' => '.portlet-decoration-'.$model->id,
  'collapsed' => '#my-portlet-'.$model->id,
  'arrow' => false,
  'easing' => 'linear',
));

Make sure "titleSelector" remains a class name (no id). Third, do not forget to pass the unique id's to your portlet as parameter "model_id" (see portlet code).

That'll do the job.

If you have multiple portlets one after another you may want to add some additional margin (top+bottom) otherwise there is no spacing when collapsed. I've done this for all portlets with the following 2 lines:

.portlet {margin-bottom:20px;}
.portlet-content {margin-bottom:0; padding-bottom:0;}

You can surely play around with the values for your liking. Have fun!

@joblo This works well on Safari 5+ & FF 3.6++ on Mac too.

#5360 report it
Alex Adams at 2011/10/06 10:48pm
Portlet specificity

Great extension. Thank you. What I need is a plan for having each portal on a page specified separately. I want some portals to initialize collapsed and others to initialize expanded.

Any ideas on how best to accomplish this?

Thanks,

Alex

#4168 report it
Joblo at 2011/06/12 06:45am
fixed in 1.1.2

Thanks trejder for your feedback.

  1. and 2. should be work now.
#3988 report it
Trejder at 2011/05/25 06:42am
Some remarks

Hi, thanks for a great extension. Here you have some remarks and things I found:

  1. I used your example from comment "easing (#3656)" for giving standard Yii portlets slide-functionality and found out that your extension changes style (background-color) of title of such protlet. It was light blue by default, it is now white.

  2. Your extension won't work in Yii earlier than 1.1.6 because in line 108 of ESlidetoggle.php you're using method chaining, not available in any previous version. Consider changing this line into standard method-by-method call and you can easily make your extension available for users of earlier versions of Yii.

Thanks again, Trejder

#3710 report it
Joblo at 2011/04/30 02:57am
Problems?

One has reported problems with 'slidetoggle' and Firefox 3.6.

Please let me know if you have problems too with a specific browser.

The examples above have been tested with:

  • Google Chrome 10
  • IE 6, IE 8
  • Firefox 3.5
  • Opera 11
#3658 report it
Joblo at 2011/04/26 03:44pm
Easing support

Added the jQuery Easing Plugin. See the usage above.

#3656 report it
Joblo at 2011/04/26 01:37pm
easing

The 'easing' method for jQuery 'slideToggle' can be set with the property 'easing' of the widget. By default the jQuery core only supports: 'linear' and 'swing'.

For more possiblities you have to register additional scripts - for example:

or

The extension 'slidetoggle' registers none of these scripts so you have to do it manually in the view. Then more easing methods are available:

Yii::app()->clientScript->registerCoreScript('jquery.ui');
//or Yii::app()->clientScript->registerScriptFile('Path to jquery.easing.1.3.js');
 
//Usage for standard Yii portlets
$this->widget('mongocms.extensions.slidetoggle.ESlidetoggle',
array(
    'itemSelector' => '.portlet',
    'titleSelector' => '.portlet-decoration',
    'easing' => 'easeInBounce', //possible effects see the links above
));

Hope that helps.

#3642 report it
Tibor Katelbach at 2011/04/26 02:59am
changing the toggling effect (currently doubles up / down action)

Hi thanks for your extension how can I change the effect of the toggle movement?

Leave a comment

Please to leave your comment.

Create extension