[EXTENSION] Bootstrap

I just made a quick test, and I confirm that setting encodeLabel to false works if you do this per-items (for a dropdown menu).

You can’t set it globally on the parent item, nor on the BootMenu itself.

This is because when rendering dropdown menu, there’s no way to modify the $encodeLabel property of BootDropdown :




// BootMenu renderItems, around line 126

if(isset($item['items']) && !empty($item['items']))

{

    $this->controller->widget('bootstrap.widgets.BootDropdown', array(

          items'=>$item['items'],

          'htmlOptions'=>isset($item['dropdownOptions']) ? $item['dropdownOptions'] : $this->dropdownOptions,

          // Maybe we should add this here to use the global BootMenu setting for dropdown

          'encodeLabel' => $this->encodeLabel,

    ));

}



Okay, just checked – the active class is indeed assigned to the parent items, however, apparently the CSS for drop down and regular items in the navbar is different for highlighted items – weird but okay I suppose.

Hello

Excuse me for my english.

Congratulations for the extension bootsrap.

but i’ve some problems to install this extension

after added this extension and modified dans my config, I reload the page.

result: this page don’t change.

why?

I ask to you if you can verify this code:

thanks a lot for your responses


<?php


// uncomment the following to define a path alias

// Yii::setPathOfAlias('local','path/to/local-folder');


// This is the main Web application configuration. Any writable

// CWebApplication properties can be configured here.

return array(

	'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..',

	'name'=>'My Web Application',


	// preloading 'log' component

	'preload'=>array('log','bootstrap',),


	// autoloading model and component classes

	'import'=>array(

		'application.models.*',

		'application.components.*',

	),


	'modules'=>array(

		// uncomment the following to enable the Gii tool

		

		'gii'=>array(

			'class'=>'system.gii.GiiModule',

			'password'=>'Enter Your Password Here',

		 	// If removed, Gii defaults to localhost only. Edit carefully to taste.

			'ipFilters'=>array('127.0.0.1','::1'),

			'generatorPaths'=>array('bootstrap.gii',),

		),

		

	),


	// application components

	'components'=>array(

		'user'=>array(

			// enable cookie-based authentication

			'allowAutoLogin'=>true,

		),

		// uncomment the following to enable URLs in path-format

		/*

		'urlManager'=>array(

			'urlFormat'=>'path',

			'rules'=>array(

				'<controller:\w+>/<id:\d+>'=>'<controller>/view',

				'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',

				'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',

			),

		),

		*/

		'db'=>array(

			'connectionString' => 'sqlite:'.dirname(__FILE__).'/../data/testdrive.db',

		),

		// uncomment the following to use a MySQL database

		/*

		'db'=>array(

			'connectionString' => 'mysql:host=localhost;dbname=testdrive',

			'emulatePrepare' => true,

			'username' => 'root',

			'password' => '',

			'charset' => 'utf8',

		),

		*/

		'errorHandler'=>array(

			// use 'site/error' action to display errors

            'errorAction'=>'site/error',

        ),

		'log'=>array(

			'class'=>'CLogRouter',

			'routes'=>array(

				array(

					'class'=>'CFileLogRoute',

					'levels'=>'error, warning',

				),

				// uncomment the following to show log messages on web pages

				/*

				array(

					'class'=>'CWebLogRoute',

				),

				*/

			),

		),

		'bootstrap'=>array(

			'class'=>'ext.bootstrap.components.Bootstrap', // assuming you extracted bootstrap under extensions

			'coreCss'=>true, // whether to register the Bootstrap core CSS (bootstrap.min.css), defaults to true

			'responsiveCss'=>false, // whether to register the Bootstrap responsive CSS (bootstrap-responsive.min.css), default to false

			'plugins'=>array(

				// Optionally you can configure the "global" plugins (button, popover, tooltip and transition)

				// To prevent a plugin from being loaded set it to false as demonstrated below

				'transition'=>false, // disable CSS transitions

				'tooltip'=>array(

					'selector'=>'a.tooltip', // bind the plugin tooltip to anchor tags with the 'tooltip' class

					'options'=>array(

						'placement'=>'bottom', // place the tooltips below instead

					),

				),

				// If you need help with configuring the plugins, please refer to Bootstrap's own documentation:


			),

		),

	),


	// application-level parameters that can be accessed

	// using Yii::app()->params['paramName']

	'params'=>array(

		// this is used in contact page

		'adminEmail'=>'webmaster@example.com',

	),

);

I’m with sebako, anyone know how to renderpartial in one of the content areas of a tab?

Hi,

These are two code snippets I’ve used – one for renderpartial and the other to dynamically load content on-click of a tab via AJAX.

The renderpartial works fine for me like this:


$this->widget('BootTabbable', array(

    'type'=>'pills',

    'tabs'=>array(

        array(

            'label'=>'Details',

            'id'=>'tab-details',

            'content'=>$this->renderPartial('_details',array(

                        'model'=>$model,

                    ), true),

        ),

));

Here’s what I use to load the content on click of the tab. In this case, we are loading serial numbers for a particular part:




        array(

            'label'=>'Serials',

            'id'=>'tab-serials',

            'ajax' => $this->createUrl('part/UpdateSerials', array('id'=>$model->id)),

        ),  



Here’s some jQuery in the same view as the serials tab above:


<script> 

  $(function () {

    $('body').on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {

      e.preventDefault()

      var tabText = e.currentTarget.text;

      if (tabText == 'Serials') {

        $.ajax({

                method:"GET",

                url: "/project/part/UpdateSerials/<?php echo$model->id;?>",

                dataType: "html",

                success: function(data) {

                    $("#tab-serials").html(data);

                }

        });      

        }      

      $(this).tab('show')


    })

  })

</script>

    

Finally, here’s the code in my PartController to render the serials CGridView:


 

   public function actionUpdateSerials($id)

    {

        

        $partSerialNumbersDataProvider = new CActiveDataProvider('PartSerialNumber',array(

            'criteria'=>array(

                    'condition'=>'part_id=:part_id',

                    'params'=>array(':part_id'=>$id),

            ),

            'pagination'=>array(

                    'pageSize'=>10,

            ),

            'sort'=>array(

                    'defaultOrder'=>'id asc',

            ),

        ));


        echo $this->renderPartialWithHisOwnClientScript('_serialNumbers',array('partSerialNumbersDataProvider'=>$partSerialNumbersDataProvider), false, true);

    }



The actual view file (_serialNumber) is pretty straightfoward – just a CGridView with a dataprovider of $partSerialNumbersDataProvider

Hope that makes sense! Works like a charm for me – lets me have a bunch of tabs who’s data doesn’t load until the user actually clicks on the tab. Also, the “renderPartialwithHisOwnClientScript” takes care of an issue I was having with the pagination for a CGridView.

Thanks for this snippet – that helps me with my jQuery calling a nicely named tab instead of yw8-tab…

My question is how to get a tab name passed in as a GET parameter to be the one that has focus on the page load??? This functionality used to work fine with the old tabs, but now I can’t get it to focus on a defined tab. For example, in a breadcrumb I would pass in the ‘#’=>‘tab-details’ to get it to load the details tab, but this no longer works.

Any thoughts?

@rums I got it working, thanks so much…

@ncramer: Thanks for noticing the bug in BootTabbale, I’ve fixed the bug in the current develop branch and the fix will be included in the upcoming release.

EDIT: corrected the credit. :)

Hi Chris,

I wish I could take credit but it was @ncramer that found the bug.

Any thoughts to my question on if it’s possible to set the active tab on load of a page by passing in the tab-id?

Thanks again for all the great work – this extension is fantastic.

Hey rums,

Do you recall if it worked in 0.9.9? Because that’s when I integrated the native jQuery plugins, before that I used my own custom widgets. I chose to use the Bootstrap JavaScript instead to fully support everything that Bootstrap itself supports.

Hi Chris,

I don’t recall it ever working with a #tab-name; at least not in my system. I did come up with a bit of a work-around, which is to add this bit of jQuery:


  $(function () {

     if (window.location.hash) {

         $('ul.nav.nav-pills > li > a[href="' + window.location.hash + '"]').click();

     }

   })

I can’t just put a .tab(‘show’) in this case as I’m rendering the content asynchronously on the click event of the tab. This functionality was built in with CJuiTabs; I guess it just doesn’t exist by default in Bootstrap.

Nope it doesn’t. Keep in mind that Bootstrap plugins are quite new and doesn’t provide even nearly as much functionality the e.g. the jQuery UI widgets do.

Hi all!

My 2 cents how to make bootstrap tabs load asyncronously

Usage of BootTabbed widget:




<?php 

	$this->widget('bootstrap.widgets.BootTabbed', array(

    'type'=>'tabs',

    'events'=>array('show'=>'js:bootstrapAjaxTabs'),

    'tabs'=>array(

        array('label'=>'Summary', 'content'=>$this->renderPartial('_view_summary', array('model'=>$model), true) ),

        array('label'=>'Memos','linkOptions'=>array(

        			'data-ajax'=>$this->createUrl('customermemo/ajaxgrid', array(

        				'id'=>$model->id,

						'scenario'=>'customer'

        			))

        		)),

        array('label'=>'Account history','linkOptions'=>array(

        			'data-ajax'=>$this->createUrl('customerbalancehistory/ajaxgrid', array(

        				'id'=>$model->id,

        				'scenario'=>'customer'

        			))

        		)),

		array('label'=>'Refferals','linkOptions'=>array(

	        		'data-ajax'=>$this->createUrl('customer/refferals', array(

	        			'id'=>$model->id

					))

				)),

    ),

)); ?>



function in my scripts.js file




function bootstrapAjaxTabs(e)

{

	var tab 	= $(e.target);

	var url		= tab.attr('data-ajax');

		

	if(url)

	{		

		tab.attr('data-ajax', null);

		var div = $(tab.attr('href'));

		div.html('<div class="loading">loading...</div>').load(url);

	}

}



Some explanation the 1 tab is preloaded through partial view, other tabs are loaded on demand through ajax only on first click, if tab clicked second time the content is already there and not reloaded.

P.S. I was using bootstrap extension 0.9.9 and I should uncomment events logic in BootTabbed.

P.P.S if anybody interested I could post snippets how to make typeahead to take data asyncronously from server as well as to integrate datepicker bootstrap plugin into extension.

Does anyone know what to do to fix this?




	$this->widget('bootstrap.widgets.BootButtonGroup', array(

        'type'=>'primary', 

        'buttons'=>array(

            array('label'=>'Categories', 'url'=>'#' ,'icon'=>'icon-edit icon-white'),

            array('items'=>array(

                array('label'=>'Action', 'url'=>'#'),

                array('label'=>'Another action', 'url'=>'#'),

                array('label'=>'Something else', 'url'=>'#'),

                array('label'=>'Separate link', 'url'=>'#'),

            )),

				),

			)); 

		?>

		</div>




Hey Chris83,

if have added this to my view


$gridDataProvider = new CArrayDataProvider(array(

	array('id'=>1, 'desc' => 'Konto', 'date' => $account->date, 'balance' => $account->balance)

));

$this->widget('bootstrap.widgets.BootGridView', array(

        	'dataProvider'=>$gridDataProvider,

        	'template'=>"{items}",

        	'itemsCssClass'=>'table table-striped table-condensed',

        	'columns'=>array(

                	array('name'=>'id', 'header'=>'#'),

                	array('name'=>'desc', 'header'=>'Description'),

                	array('name'=>'date', 'header'=>'Date'),

                	array('name'=>'balance', 'header'=>'Amount'),

                	array(

                    	'class'=>'bootstrap.widgets.BootButtonColumn',

                    	'htmlOptions'=>array('style'=>'width: 50px'),

                	),

            	),

    	)

);

But I get “Trying to get property of non-object in /var/yii/base/CComponent.php(607) : eval()'d code(1)”. Must be something with


array(

                    	'class'=>'bootstrap.widgets.BootButtonColumn',

                    	'htmlOptions'=>array('style'=>'width: 50px'),

                	),

because when I leave this snippet out, everything works and I get the table displayed. Any suggestions?

Try using BootButtonColumn instead of bootstrap.widgets.BootButtonColumn.

Then I am getting this

“include(BootButtonColumn.php): failed to open stream: No such file or directory in /var/yii/YiiBase.php(418)” :(

This “‘class’=>‘bootstrap.widgets.BootButtonColumn’,” ist from the Demo page of Chris83 bootstrap extension.

[s]Since jquery is not my specialty, could you quickly elaborate on the simpler method since I’m not relying on async loading?

[/s]

Edit: Nevermind, google is a wonderful thing. I think this is all you meant??




$('ul.nav.nav-tabs > li > a[href=\"' + window.location.hash + '\"]').tab('show');



Thanks,

nc

I am trying to create a normal AjaxButton, but it is calling the wrong URL


<?php $this->widget('bootstrap.widgets.BootButton', array(

            	'fn'=>'ajaxLink',

            	'label'=>'Edit profile',

            	'type'=>'', // '', 'primary', 'info', 'success', 'warning', 'danger' or 'inverse'

            	'size'=>'small', // '', 'small' or 'large'

            	'htmlOptions'=>array(

                	'class' => 'pull-right',

                	'href' => $this->createUrl('/user/edit',

                                          	array('id'=>$user->id,

                                                	'section'=>'profile')

                                        	)   

            	),

        	)); ?>



Is there anything wrong with the code and where can I specify the target div where the new content should be loaded in?

Looks to me like the image I posted in my last question is unavaileble:s

Anyone, what happens is I create a BootButtonGroup.

The "button" looks like It should, but the "dropdown-part" is smaller in size, somewhere 60-70% the height of the button. I copied the code from the demo page so its very weird, what can affect this?