Yii 1.1: quickdlgs

Simplifies the usage of CJuiDialog and Fancybox
38 followers

Render buttons/links/icons to display a CJuiDialog with a content / ajax-response / iframe with a single line of code.

Replace the standard CButtonColumn with the EJuiDlgsColumn of this extension to open the view and update action in a dialog like explained in the wiki articles (see Resources).

Easy using of the jQuery fancybox plugin. Works inside a ajax-enviroment.

Requirements

Developed with Yii 1.1.10

Installation

Extract the zip file into protected/extensions.

Register the components in the import section of config/main.php

// autoloading model and component classes
    'import'=>array(
        ...
        'ext.quickdlgs.*',
    ),

Usage

Use the static methods from the EQuickDlgs class in a view to render buttons/links/icons to open a dialog. Take a look at the methods/parameters in the source of EQuickDlgs.php.

1. The simple content-dialog

For example this can be used to display a 'More info' or 'Help' button in a form.

EQuickDlgs::contentButton(
 array(
     'content' => 'This is the help text', //$this->renderPartial('_help',array(),true),
     'dialogTitle' => 'Help',
     'dialogWidth' => 200,
     'dialogHeight' => 300,
     'openButtonText' => 'Help me',
      'closeButtonText' => 'Close', //comment to remove the close button from the dialog
     )
  );

Use EQuickDlgs::contentLink, EQuickDlgs::contentIcon and EQuickDlgs::contentPopup the same way.

Note:

All the content of the dialog will be loaded together with the page. Use an ajax-button, if you want to load the dialogcontent on the first button-click.

2. The ajax-dialog

A icon for the view action of the current or another controller. You have to specify the 'controllerRoute' and the 'actionParams'

EQuickDlgs::ajaxIcon(
            Yii::app()->baseUrl .'images/view.png',
            array(
                'controllerRoute' => 'view', //'member/view'
                'actionParams' => array('id'=>$model->id), //array('id'=>$model->member->id),
                'dialogTitle' => 'Detailview',
                'dialogWidth' => 800,
                'dialogHeight' => 600,
                'openButtonText' => 'View record',
                'closeButtonText' => 'Close',
            )
        );

If you 'reuse' a default controller view action inside a dialog, the full page (with header, menu ...) will be displayed. You have to 'renderPartial' instead of 'render'.

You simply have to replace the controller->render with EQuickDlgs::render. This will check if the request comes from a dialog. So it will work the standard way or within a dialog.

public function actionView($id)
            {
                EQuickDlgs::render('view',array('model'=>$this->loadModel($id)));
                //$this->render('view',array('model'=>$this->loadModel($id)));
            }

Note:

You will have problems if you show list, create, update, admin action views inside an ajax-dialog, because the javascript (pagination ...) will not work as expected.

You can use an iframe-dialog instead of the ajax for that purpose.

Other ajax functions: EQuickDlgs::ajaxLink, EQuickDlgs::ajaxButton, EQuickDlgs::ajaxPopup

3. The iframe-dialog

A remote url as iframe-dialog:

EQuickDlgs::iframePopup(
                    array(
                    'url' => 'http://www.yiiframework.com',
                    'dialogWidth' => 1024,
                    'dialogHeight' => 768,
                    'hideTitleBar' => true,
                    'closeButtonText' => 'Close', 
                    );

If you want to place a 'Create' button in a admin-view above the CGridView:

EQuickDlgs::iframeButton(
    array(
        'controllerRoute' => 'create',
        'dialogTitle' => 'Create item',
        'dialogWidth' => 800,
        'dialogHeight' => 600,
        'openButtonText' => 'Create new',
        'closeButtonText' => 'Close',
        'closeOnAction' => true, //important to invoke the close action in the actionCreate
        'refreshGridId' => 'group-grid', //the grid with this id will be refreshed after closing
    )
);

In this case you have to make a few changes to the actionCreate method of the controller, because the dialog should be closed after saving the record.

The content should be rendered into a 'iframe' layout, because the application header, menu ... should not be visible, but the css/js-files should be present.

Edit and modify the default iframe-layout-file 'ext.quickdlgs.layouts.iframe' for your needs.

Like above, the EQuickDlgs::render method will do the rest.

public function actionCreate()
{
    ....
 
        if(model->save())
        {
            //close the dialog and update the grid instead of redirect if called by the create-dialog
            EQuickDlgs::checkDialogJsScript();
            $this->redirect(array('admin'));
        }
 
        //check if the iframe layout (or renderPartial) has to be used
        EQuickDlgs::render('create',array('model'=>$model));
        //$this->render('create',array('model'=>$model));
}

Other iframe functions: EQuickDlgs::iframeLink, EQuickDlgs::iframeIcon

4. The EJuiDlgsColumn

This buttoncolumn can be used as replacement for the standard CButtonColumn. It overrides the 'view' and 'update' buttons, the 'delete' or other custom buttons will work like inside the CButtonColumn.

'id'=>'group-grid',
    'dataProvider'=>$model->search(),
    'columns'=>array(
            'id',
            'name',
              ....
            ),
 
    array(
       'class'=>'EJuiDlgsColumn',
 
       //configure like CButtonColumns:
       //but some properties (buttons.view.url,buttons.view.id, buttons.view.ajax, buttons.update.click  ...) will be set by the component
 
       //'template'=>'{view}',
       'viewButtonImageUrl'=>Yii::Yii::app()->baseUrl .'images/dialogview.png',
       'buttons'=>array(
            'view' => array(
                'label'=> 'ajax dialog view',
            ),
 
            'delete' => array(
                                'label'=> 'someLabel',
                                ),
            ),
 
  //---------- additional config for the dialogs starts here -------------
 
        //if you want to use a custom dialog config: default is  'ext.quickdlgs.juimodal'
        //'viewDialogConfig' => 'ext.quickdlgs.mycustomjuiattributes'
 
       //don't override the CButtonColumn view button
       //'viewDialogEnabled' = false,
 
        //the attributes for the EAjaxJuiDlg widget: use like the 'attributes' param from EQuickDlgs::ajaxButton above
        'viewDialog'=>array(
             //'controllerRoute' => 'view', //=default
             //'actionParams' => array('id' => '$data->primaryKey'), //=default
             'dialogTitle' => 'View detail',
                         'hideTitleBar' => true, 
             //'dialogWidth' => 800, //use the value from the dialog config
             //'dialogHeight' => 600,
        ),
 
        //the attributes for the EFrameJuiDlg widget. use like the 'attributes' param from EQuickDlgs::iframeButton
        'updateDialog'=>array(
               //'controllerRoute' => 'update', //=default
               //'actionParams' => array('id' => '$data->primaryKey'), //=default
               'dialogTitle' => 'View detail',
               'dialogWidth' => 1024, //override the value from the dialog config
               'dialogHeight' => 600,
            ),
      ),
    ),

See the code of the EJuiDlgsColumn for more options.

As a descandant of the CButtonColumn all other attributes/possibilities are the same.

The default attributes are generated from the file 'ext.quickdlgs.config.juimodal'. You can change this by setting the property 'viewDialogConfig'.

Important:

The button 'view' will open an ajax-dialog, the 'update' an iframe-dialog. So you have the change the code of the actionView and the actionCreate like above.

public function actionView($id)
{
   EQuickDlgs::render('view',array('model'=>$this->loadModel($id)));
   //$this->render('view',array('model'=>$this->loadModel($id)));
}
 
public function actionUpdate($id)
{
    ....
 
        if(model->save())
        {
            //close the dialog and update the grid instead of redirect if called by the update-dialog
            EQuickDlgs::checkDialogJsScript();
            $this->redirect(array('admin','id'=>$model->id));
        }
 
        //check if the iframe layout (or renderPartial) has to be used
        EQuickDlgs::render('update',array('model'=>$model));
        //$this->render('update',array('model'=>$model));
}

The EJuiDlgsColumn does all the coding explained in the wiki-articles.

Tip: You can add an additional buttoncolum to list the records of a related model.

Assume you have a 'function actionList($parentId)' in a MemberController with a view that uses CListView and the records are filtered by the 'parendId'.

Because of the js-code in the view (CListView with pagination...) you should use the iframe-dialog of the 'update' button (not the ajax of the view button).

$this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'mygrid',
    'dataProvider'=>$model->search(),
    'columns'=>array(
        'id',
        'name',
                ...
 
        array(
            'class'=>'EJuiDlgsColumn', //all default for the view, update
          ),
 
        array(
            'class'=>'EJuiDlgsColumn',
            'template'=>'{update}',
            'updateButtonImageUrl'=>Yii::Yii::app()->baseUrl .'images/viewdetaildialog.png',
            'updateDialog'=>array(
               'controllerRoute' => 'members/list', 
               'actionParams' => array('parentId'=>'$data->id'),
               'dialogTitle' => 'View detail',
               'dialogWidth' => 1024, //override the value from the dialog config
               'dialogHeight' => 600,
            ),            
          ),
    ),

5. Fancybox

Use the EFancybox widget and place the items inside beginWidget and endWidget.

$widget=$this->beginWidget('ext.quickdlgs.EFancybox');
 
            $widget->image($smallImageUrl,$largeImageUrl); //show a image-fancybox
            $widget->content('Some text','Lorem ipsum dolor sit amet, consectetur adipiscing elit',array('title'=>'This is the title')); //show content in a fancybox
            $widget->url('A fancy ajax content',$this->createUrl('fancycontent')); //ajax content
            $widget->url('Yii','http://www.yiiframework.com',array(),true); //iframe content
 
   $this->endWidget();

Set the fancybox options by setting 'imageOptions', 'contentOptions' and/or 'urlOptions'

$widget=$this->beginWidget('ext.quickdlgs.EFancybox',
                            array(
                                    'easing'=>true,
                                    'imageOptions' => array(
                                                            'overlayColor' => '#000',
                                                            'overlayOpacity' => 0.9,
                                                            'transitionIn' => 'elastic',
                                                            'transitionOut' => 'elastic',
                                                            'speedIn' => 600,
                                                            'speedOut' => 200,
                                                    ),
                            );
 
            $widget->image($smallImageUrl1,$largeImageUrl1);
            $widget->image($smallImageUrl2,$largeImageUrl2);
            ...
 
   $this->endWidget();

The Fancybox widget supports ajax, that means it can be used inside a ajax-environment. IMPORTANT: In this case you have to set the property directOutput=true or Yii::app()->request->isAjaxRequest.

Album example with a CListView:

Your 'album' view

$items = array();
$items[] = array('imgUrlSmall'=>...,'imgUrlLarge'=>..);
$items[] = array('imgUrlSmall'=>...,'imgUrlLarge'=>..);
...
 
   $dataProvider = new CArrayDataProvider($items, array(
            'keyField'=>'imgUrlSmall',
            'pagination'=>array(
                'pageSize'=>5,
            ),
        ));
 
 
        $fancyWidget=$this->beginWidget('ext.quickdlgs.EFancybox',array(
            'directOutput'=>Yii::app()->request->isAjaxRequest, //important because of ajax pager
            'imageOptions'=>array(
                'width'=>1024,
                'height'=>576,
            )
        ));
 
        $this->widget('zii.widgets.CListView', array(
            'dataProvider'=>$dataProvider,
            'itemView'=>'_album',
            'viewData' => array('fancyWidget'=>$fancyWidget),
        ));
 
        $this->endWidget();

Your _album view

...
 $fancyWidget->image($data['imgUrlSmall'],$data['imgUrlLarge']);
 ...

Resources

Changelog

  • v2.0:

    • Added fancybox widget: EFancybox.php (MIT License)
    • Included fancybox-1.3.4 (v2+ is only free for personal use)
  • v1.2:

    • Fallback for link-tag when javascript is disabled
    • contentwrapper visibility is false, set visible on open
    • New attribute 'hideTitleBar' //default = false (sometimes ui dialog looks better)
    • New EQuickDlgs::contentPopup,EQuickDlgs::iframePopup,EQuickDlgs::ajaxPopup with autoopen=true
  • v1.1: Changed EJuiDlgsColumn.php

    • some bugfixes (thanks to c@cba for his comment)
    • Changed the properties of EJuiDlgsColumn (not compatible with v1.0).
      Removed 'viewDialogHeight', .... Added 'viewDialog', 'updateDialog' instead to assign all dialog attributes like EQuickDlgs::ajaxButton / EQuickDlgs::iframeButton.
      It's more flexible and you can add 'dialogAttributes' with theme/themeurl... too.

Total 20 comments

#16803 report it
Scott_Huang at 2014/03/30 12:40am
Great Extention, Thank you Joblo

I like it, thanks.

Great Yii and team contribution!

#13296 report it
yiqing95 at 2013/05/21 06:27am
iframe height has some problem

in some browsers the height="100%" do not work . blow is what i v modified (EFrameJuiDlg::renderDialogContent) :

if(isset($this->iframeHtmlOptions['height'])){
            $defaultOptions = array('width' => '100%', 'src' => $src, 'id' => $this->getFrameId());
        }else{
            $defaultOptions = array('width' => '100%','height' => '100%', 'src' => $src, 'id' => $this->getFrameId());
        }
 
        $htmlOptions = array_merge($this->iframeHtmlOptions, $defaultOptions);

or for simple just do it this way :

$htmlOptions = array_merge(array('width' => '100%', 'height' => '100%', 'src' => $src, 'id' => $this->getFrameId()),$this->iframeHtmlOptions);

exchange the the order of defaultOptions and the iframeHtmlOptions

after do this we can explicity specify the "height" for the iframe using iframeHtmlOptions attribute !

#13198 report it
Joblo at 2013/05/13 09:06am
urlparams

Is it right, that you you didn't set the urlManager->urlFormat to 'path'?

The problem is, that it depends on the settings of the Yii urlManager (and maybe the rules) if I have to add more urlparams as '?....' or '&....'.

If the urlManager is set to 'urlFormat'=>'path' then a '?' is needed otherwise a '&'. To fit both urlManager settings, a possible solution in the EJuiDlgsColumn::createButtonUrl could be:

$paramChar = Yii::app()->urlManager->urlFormat=='path' ? '?' : '&';
            $url .= '"'.$paramChar . http_build_query($params) . '"';

Does this work for you?

#13197 report it
jward at 2013/05/13 08:02am
@PeRoChAk

That's the same comment I referenced in my comment but the solution hasn't worked it's way into the extension yet. There are now at least two places this solution is needed.

#13189 report it
PeRoChAk at 2013/05/13 03:16am
@jward

Check

http://www.yiiframework.com/extension/quickdlgs/#c8800

#12782 report it
jward at 2013/04/12 12:32am
EJuiDlgsColumn dialog didn't close (fixed?)

When using EJuiDlgsColumn to create a dialog, I couldn't get the dialog to close automatically until I changed line 426 from

$url .= '"?' . http_build_query($params) . '"';

to

$url .= '"&' . http_build_query($params) . '"';

I couldn't get it to work as expected otherwise. This problem is similar to #8800: Problem with URL but I didn't make the same change to account for not having the url provided.

#10845 report it
Joblo at 2012/11/27 06:56am
Ajax

I have solved the ajax-problem in the Fancybox feature.

But in the moment it seems to be nearly impossible to do the same with a CJuiDialog without hacking the core.

I started a topic here

#10605 report it
kfahmi at 2012/11/07 10:31am
@imre or anybody else, please help me

please help me, click this link below, please please help me any one T_T

something went wrong with my dialog (quickdlgs)

My thread, Help meeee..

#10604 report it
Imre at 2012/11/07 03:47am
@khafmi

Don't reload page with ajax where you defined your dialog:

in view file:

// used by grid button
EQuickDlgs::iframeButton(
        array(
            'id' => 'my-awsome',
            'renderOpenButton' => false, // <-----------------
            'controllerRoute' => 'awsome',
            'dialogTitle' => 'My Awsome Thing',
            //'dialogWidth' => 800,
            //'dialogHeight' => 800,
            'closeOnAction' => true, //important to invoke the close action in the actionCreate
        )
);
 
// grid column definition (or in any other ajax use the click part)
        array(
            'class' => 'EJuiDlgsColumn',
            'template' => '{mybutton}',
            'buttons' => array(
                'assign' => array(
                    'label' => 'Hover text',
                    'imageUrl' => Yii::app()->baseUrl.'/images/awsome.png',
                    'url' => 'Yii::app()->createUrl("/product/awsome", array("id"=>$data->id))',
                    'click' => "function(){
                        $('#my-awsome-frame').attr('src',$(this).attr('href')+(($(this).attr('href').indexOf('?') >= 0)?'&':'?')+'qdsClass=EFrameJuiDlg&qdsDialogId=my-awsome-dlg&qdsContentWrapperId=my-awsome-content&qdsIFrameId=my-awsome-frame&qdsCloseDialog=1');$('#my-awsome-content').show();$('#my-awsome-dlg').dialog('open');return false;
                    }",
                ),
            ),
        ),
#10603 report it
kfahmi at 2012/11/06 10:23pm
AfterAjaxUpdate,

What should i do, if the CListView doing ajax update, quickdlgs popup doesnt works. i must refresh page to make popup works again. please help me, what should i do.

#10221 report it
yiqing95 at 2012/10/11 10:48pm
it is possible work with bootstrap now

some people may know that the bootstrap may have some conflicts to the jqueryUi . but now the another bootstrap extension come to us Yii-Booster , and this extension introduce the small set of jqueryUi components to bootstrap see JqueryUi in Bootstrap

#10215 report it
Deepak Pradhan at 2012/10/11 05:49pm
I wish I cud give 2 thumbs up

:)

#9871 report it
Imre at 2012/09/17 01:35pm
small cosmetixc fixes

Worked fine in Chrome, but

added in extensions config/juimodal.php to fix height for IE8 and firefox:

'contentWrapperHtmlOptions' => array('style'=>'height: 100%;'),

added in EFrameJuiDlg.php to show no border for IE8

line 123: 
'frameborder' => 0,
#8800 report it
PeRoChAk at 2012/06/27 02:01pm
Problem with URL

There seems to be bug in code in EAjaxJuiDlg.php(line 82) and EFrameJuiDlg.php(line 80)

There should be code like as

$paramChar = strpos($url,'?') === false ? '?' : '&';            
            $url .=$paramChar . http_build_query($this->urlParams);

instead of

$url .='?'. http_build_query($this->urlParams);
#8713 report it
Joblo at 2012/06/20 04:33pm
Forum topic

Please use this forum topic to discuss this extension.

#8712 report it
Joblo at 2012/06/20 04:32pm
@bonnie: link fallback when javascript is disabled

Change the generation of the link code in EBaseJuiDlg::renderButton to

public function renderButton($config)
    {
        ...
        elseif ($type == 'link')
        {
            $url = method_exists($this,'getActionUrl') ? $this->getActionUrl() : '#';
            echo CHtml::link($text, $url, $buttonHtmlOptions);
        }
        else
            throw new CException('invalid buttontype: ' . $type);
    }

Thanks for the hint, I will do this in the next release.

But don't uncomment line 332, the EJuiDlgsColumn will not work. I have changed my answer below...

#8709 report it
bonnie at 2012/06/20 10:20am
Thanks uncommenting line 332 worked

Thanks uncommenting line 332 worked. Now one more help when the javascript is disabled how can we let the url open the request content normal as ordinary url incase the dialog fails. In one of my files I had implemented like this so that when js is enabled the dialog open and if js is disabled the url will point to the respective page normal way. Thanks.

echo CHtml::link('view', array('user/view'), array('onclick' => "js:$('#dialogid').dialog('open'); return false;"));
#8705 report it
Joblo at 2012/06/20 10:01am
display: none

You can set the property 'contentWrapperHtmlOptions'=>array(style=>'display:none') in the config/juimodal.php or in the attributes when calling EQuickdlgs::xxx

Best regards

#8703 report it
bonnie at 2012/06/20 09:37am
Nice

I have tested it but need a way to not show the content in case javascript is disable where can I include something like the code below.

<div style="display:none;"></div>

Thanks for the hard work.

#8699 report it
Joblo at 2012/06/20 06:36am
version 1.1

c@cba, thanks for this hint. I have found some more bugs in v1.0 :-(

In v1.1 I did change the properties from EJuiDlgsColumn for more flexibility, not compatible with v1.0. Hope upgrading its not to much work for those who are using this component.

Leave a comment

Please to leave your comment.

Create extension