RSS
 

Posts Tagged ‘PHP’

CakePHP, draggable/droppable in jQuery

27 Mar

Working on bunch of CRUD routines in CakePHP, I finally got tired of multiple checkboxes and decided to write a small helper for jQuery UI drag-n-drop functionality.

In response to Teknoid post, I’ve made couple of additional tweaks to dynamic select boxes, and got quite nice combination of selectboxes and dynamic lists.

The main requirement of the script was:

  1. On Selectbox value changed, return the list of related items (in #base-list div-element)
  2. Add drag/drop functionality to the base-list ul elements as well as add arrow-west/arrow-east addition/deletion of the elements
  3. After all the movements are over, to be able to save dragged values in CakePHP form to be saved.
  4. Result: here.
  5. Sample MySQL DB file: Here

The view/helpers/droppable.php looks like:

 tag
    */
    function droppableElements($outside = false) {
        $js_code = "";
 
        $js_code = '
                    var $baseDiv = $(\'#base-list\');
                    var $targetDiv = $(\'#target-list\');
 
                    $(\'li\', \'#baseUl\' ).draggable({
                        accept: \'#baseUl > li\',
                        revert: \'invalid\',
                        helper: \'clone\',
                        cursor: \'move\'
                    }); 
 
                    $(\'li\', \'#targetUl\' ).draggable({
                        accept: \'#targetUl > li\',
                        revert: \'invalid\',
                        helper: \'clone\',
                        cursor: \'move\'
                    }); 
 
                    $targetDiv.droppable({
                        accept: \'#baseUl > li\',
                        activeClass: \'ui-state-highlight\',
                        drop: function(ev, ui) {
                            moveItem(ui.draggable, $targetDiv);
                        }
                    });
 
                    $baseDiv.droppable({
                        accept: \'#targetUl > li\',
                        activeClass: \'ui-state-highlight\',
                        drop: function(ev,ui) {
                            moveItem(ui.draggable, $baseDiv);
                        }
                    });
 
                    $(\'#baseUl > li\').click(function(ev){
                        moveItemClicked($(this), $(this).parent());
                    });
 
                    $(\'#targetUl > li\').click(function(ev){
                        moveItemClicked($(this), $(this).parent());
                    });';
 
            if($outside) {
                $this->out .= $this->Javascript->codeBlock($js_code);
                return $this->out;
            } else {
                return $js_code;
            }
 
    }
 
    /*
    *   @var string $boxId - observed selectBox id element
    *   @var string $eventType - default 'change'
    *   @var string $jsonAction - method call, i.e '/departments/ajax_get_list/departments/company_id/'
    */
 
    function observeSelectBox($boxId, $eventType = 'change', $jsonAction) {
        $js_script = "";
 
        $js_script ='
          $(\'#'.$boxId.'\').live(\''.$eventType.'\', function(){
            if($(this).val().length != 0) {
            $.getJSON(\''.$jsonAction.'\',
                {searchParam: $(this).val() }, 
 
                function(items) {
                    $(\'.jq_list\').remove();
                    generateBaseList(items);
 
                '.$this->droppableElements().'
                }
            );
        }
        } );';
 
        $this->out .= $this->Javascript->codeBlock($js_script);
 
        return $this->out;
    }
 
}?>

For using so-called ajax_get_list method, I’ve written a small function in app/app_controller.php that get all the id,name list array based on couple of arguments:

In order to use this method, you should have a small layout in related views folder, that looks like:

<?php
    // somewhere in views/departments/ajax_get_list.ctp
   if(isset($items)) {
        echo $javascript->object($items);
 }?>

The view of ajax_get_list method will output serialized array of the method. For the initial view, you need to add 2 div-elements and one select box. Div elements have static id’s which are used by jQuery script to look-up (base-list, and target-list).
In our view, it should look like:

<?php  echo $droppable->observeSelectBox('company-id','change','/departments/ajax_get_list/departments/company_id/');?>
 
        <label> Load company departments: </label>
        <?php print $form->select('Company.id', $companies, null, array('id'=>'company-id'), 'Company Departments);?>
 
        <?php print $html->div('right block', $html->div('target-title', 'Container', array(), false),array('id'=>'target-list'),false);?> 
 
        <?php print $html->div(null,null, array('id'=>'base-list'));
?>

And that’s about it, once you finish dragging the li-elements to the target-list, and save the form, its values will appear in ['Container']['item_ids'] array where you can do whatever you want with it.
To make things simple, you can download a small sample of code of these files here, as well as database sample file.

 

CakePHP: remove tmp folder from svn control

01 Mar

We’d have to use propset command from SVN.

$#: cd /path/to/repository/cake_project
$#: svn delete app/tmp/*
$#: svn propset svn:ignore '*' tmp/

Now, after you commit the changes your tmp/files won’t be commited to the SVN repo.

 

CakePHP: named over url parameters passing

05 Jan

Playing around with CakePHP parameters passing through URL, I’ve noticed that using Paginator helper for listing entities mixes up named and url params in the URL.

For instance, classical paginator URL is:

http://domain.com/controller/action/page:number


which looks like:

Array(
[named] =>Array(
[page] => number
)
)

Any parameter used in the Paginator goes inside of the URL and doesn’t affect the behaviour (in my case, URL param is used for language switching), i.e. http://domain.com/controller/action/?param=foo/page:number
No matter what your $this->params['url']['param'] contains – it won’t reflect on the logic.
Thus, if we use another variable $this->params['named']['foo'], we can always access it in our viewers and utilize it in the $paginator variable, so our URL will look like:
http://domain.com/controller/action/page:number/foo:bar
Useful links:
Additional parameters in $paginator

 

CakePHP: lists, beautiful bits

18 Aug

These tiny bits of beauty really make the development enjoyable:


$names = $this->find('list', array(
'conditions'=> null,
'order' => 'Developer.id ASC',
'fields' => array('Developer.id','Developer.'.$name.''),
'recursive' => 0
));

as the result, getting:

Array = (
[1] => 'Pafilia',
[2] => 'Vashiotis'
);

I’ll miss these features if I move from this framework :)