First i created a model named Datagrid.php. In future i will pass every parameter to this model.
Datagrid.php
<?php
class Datagrid extends Zend_Db_Table
{
public $current_page = 1;
public $step = 1; // Default Step
public $order = 'id'; // Default order field
public $order_dir = 'ASC'; // Default order direction
/* Bulk Commands */
public $enable_bulk_commands = 0;
public $bulk_command_array = array('delete', 'enable', 'disable');
/* Bulk Commands */
/* Special Fields */
public $special_array = array('admin_list', 'user_list');
public $special = '';
/* End of Special Fields */
private $col_list = array();
public $column_names = array();
public $class_array = array();
public $enable_status_field_image = 1;
private $controller = '';
private $action = '';
private $baseUrl = '';
private $number_of_pages = 1;
private $item_quantity = 0;
private $item_data = array();
private $delete_button_enabled = 0;
private $delete_button_controller = '';
private $delete_button_action = '';
private $edit_button_enabled = 0;
private $edit_button_controller = '';
private $edit_button_action = '';
public function Datagrid(&$view) {
$this->db = Zend_Registry::getInstance()->get('db');
$this->view = $view;
$this->controller = $this->view->controller; // Your current controller
$this->action = $this->view->action; // Your current action
$this->baseUrl = $this->view->baseUrl; // Base url to your site axample ("http://localhost/mysite" or "http://www.mysite.com")
}
public function generateZendSql($sql){
if( empty($sql) ){
return null;
}
if( !empty($this->order) && !empty($this->order_dir) && in_array(strtoupper($this->order_dir), array('ASC', 'DESC')) ){
$sql->order("$this->order $this->order_dir");
}
$sql->limitPage($this->current_page, $this->step);
$this->item_data = $this->db->fetchAll($sql);
$this->item_quantity = $this->db->fetchOne('select FOUND_ROWS()');
$this->calculateNumberOfPages();
$this->createTable();
$this->setView();
}
public function generateArray($array){
if( empty($array) ){
return null;
}
/* Array Order */
if( !empty($this->order) && !empty($this->order_dir) && in_array(strtoupper($this->order_dir), array('ASC', 'DESC')) ){
foreach ($array as $key => $row) {
$sort_data[$key] = $row[$this->order];
}
if( $this->order_dir == "ASC" ){
array_multisort($sort_data, SORT_ASC, $array);
}else{
array_multisort($sort_data, SORT_DESC, $array);
}
}
/* End of Array order */
$this->item_quantity = count($array);
/* Calculating limit/page */
$i = 0;
foreach($array as $item){
if( $i >= (($this->current_page * $this->step)-$this->step) && $i < (($this->step *$this->current_page)) ){
$item_data[] = $item;
}
$i++;
}
/* End of calculating limit/page */
$this->item_data = $item_data;
$this->calculateNumberOfPages();
$this->createTable();
$this->setView();
}
private function setView(){
$this->view->current_page = $this->current_page;
$this->view->step = $this->step;
$this->view->order = $this->order;
$this->view->order_dir = $this->order_dir;
$this->view->item_quantity = $this->item_quantity;
$this->view->item_data = $this->item_data;
$this->view->number_of_pages = $this->number_of_pages;
}
public function calculateNumberOfPages(){
if( !empty($this->item_quantity) && $this->item_quantity > 0 ){
if( ( $this->item_quantity % $this->step ) > 0 ){
$this->number_of_pages = ceil( $this->item_quantity/$this->step );
}else{
$this->number_of_pages = $this->item_quantity/$this->step;
}
}else{
$this->number_of_pages = 1;
}
}
public function setParams($page = 0, $step = 0, $order = '', $orderdir= ''){
// page - current page
// step - table pagination step
// order - order filed
// orderdir - ( ASC, DESC ), default -> ASC
if( !empty($page) && intval($page) > 0 ){
$this->current_page = intval($page);
}
if( !empty($step) && intval($step) > 0 ){
$this->step = intval($step);
}
if( !empty($order) ){
$this->order = $order;
}
if( !empty($orderdir) && in_array(strtoupper($orderdir), array('ASC', 'DESC')) ){
$this->order_dir = strtoupper($orderdir);
}
}
private function createTable(){
$columns = $this->getHeaderCols();
$html = "";
if( !empty($this->item_data) && !empty($columns) ) {
if( $this->delete_button_enabled == 1 ){
$html .= "
<script type='text/javascript'>
$(document).ready(function(){
$('a.grid_delete_item').live('click', function(event){
event.preventDefault();
var href = $(this).attr('href');
var question_text = 'Are you sure to delete?';
apprise(question_text, {verify : true}, function(r) {
if(r){
window.location.href = href;
}else{
event.preventDefault();
}
});
});
});
</script>";
}
$filtoptions = "/order/$this->order/orderdir/$this->order_dir/step/$this->step";
$html .= "<table cellspacing='0' cellpaddin='0' class='grid'>";
/* Table header */
$html .= "<tr class='grid_head_tr'>";
if($this->delete_button_enabled == 1 && $this->edit_button_enabled == 1){
$html .= "<td class='grid_head_td' colspan='2'> </td>";
}else{
if( $this->delete_button_enabled == 1 ){
$html .= "<td class='grid_head_td'> </td>";
}
if( $this->edit_button_enabled == 1 ){
$html .= "<td class='grid_head_td'> </td>";
}
}
foreach( $columns as $key=>$col ){
$html .= "<td class='grid_head_td'>";
if( !($this->order_dir == "ASC" && $this->order == $this->col_list[$key]) ){
$html .= "<a href='".$this->baseUrl . "/" . $this->controller."/".$this->action."/page/".$this->current_page."/order/".$this->col_list[$key]."/orderdir/ASC/step/".$this->step."'><img class='order_img' src='".$this->baseUrl."/gfx/grid/arrow-up.png' /></a>";
}
$html .= "$col";
if( !($this->order_dir == "DESC" && $this->order == $this->col_list[$key]) ){
$html .= "<a href='".$this->baseUrl."/".$this->controller."/".$this->action."/page/".$this->current_page."/order/".$this->col_list[$key]."/orderdir/DESC/step/".$this->step."'><img class='order_img' src='".$this->baseUrl."/gfx/grid/arrow-down.png' /></a>";
}
$html .= "</td>";
}
$html .= "</tr>";
/* End of table header */
/* Datagrid items */
$i = 0;
foreach( $this->item_data as $item ){
if($i%2 == 0) $hl = " class='alt'"; else $hl = "";
$html .= "<tr$hl>";
if( $this->delete_button_enabled == 1 ){
$html .= "<td class='content textCenter'><a class='tippsy grid_delete_item' original-title='Delete' href='".$this->baseUrl."/".$this->delete_button_controller."/".$this->delete_button_action."/id/".$item['id']."'><img src='".$this->baseUrl."/gfx/grid/delete.png' alt='delete' /></a></td>";
}
if( $this->edit_button_enabled == 1 ){
$html .= "<td class='content textCenter'><a class='tippsy' original-title='Edit' href='".$this->baseUrl."/".$this->edit_button_controller."/".$this->edit_button_action."/id/".$item['id']."'><img src='".$this->baseUrl."/gfx/grid/edit.gif' alt='edit' /></a></td>";
}
foreach( $item as $field => $data ){
if( in_array($field, $this->col_list) ){
if( $field == "enabled" && $this->enable_status_field_image ){
// Enabled image
$enabled_image = ($data == 1) ? "enabled.gif": "disabled.gif";
if( !empty($this->class_array[$field]) ){
$html .= "<td class='content ".$this->class_array[$field]."'><img src='".$this->baseUrl."/gfx/grid/".$enabled_image."' alt='status' /></td>";
}else{
$html .= "<td class='content'><img src='".$this->baseUrl."/gfx/grid/".$enabled_image."' alt='status' /></td>";
}
// End of enabled image
}else{
if( empty($data) ){
$data = "---";
}
/* just for fields created, modified */
if( in_array($field, array('created', 'modified')) ){
if( $data == "0000-00-00 00:00:00" ){
$data = '---';
}
}
/* --------------------------------- */
if( !empty($this->class_array[$field]) ){
$html .= "<td class='content ".$this->class_array[$field]."'>".$data."</td>";
}else{
$html .= "<td class='content'>".$data."</td>";
}
}
}
}
$html .= "</tr>";
$i++;
}
/* End of datagrid items */
/* Page Numbers */
$col_number = count($this->col_list);
if( $this->delete_button_enabled == 1 ){
$col_number++;
}
if( $this->edit_button_enabled == 1 ){
$col_number++;
}
$html .= "<tr class='grid_footer_tr'>";
$html .= "<td class='grid_footer_td' colspan='".$col_number."'>";
$html .= "<div style='width:100%;'>";
/* Left side info */
$html .= "<div class='fl'>Quantity: ".$this->item_quantity." | Page ".$this->current_page." of ".$this->number_of_pages." | Step <form action='".$this->baseUrl."/".$this->controller."/".$this->action."' method='post' style='display:inline'>";
$html .= "<select name='step'>";
$stepArray = array(1,3,5,7,10,15,20,25,30,40,50,75,100);
foreach( $stepArray as $step ){
if( $step == $this->step ){
$html .= "<option value='$step' selected='selected'>$step</option>";
}else{
$html .= "<option value='$step'>$step</option>";
}
}
$html .= "</select><input type='hidden' name='order' value='".$this->order."' /><input type='hidden' name='orderdir' value='".$this->order_dir."' /> <input class='grid_submit_btn' type='submit' value='Change' /></div>";
/* End of left side info */
/* Pagination */
if($this->number_of_pages > 1){
$html .= "<div class='fr pagination'>";
// add order + step
if( $this->current_page != 1 ){
$html .= "<a class='pagination_lnk' href='".$this->baseUrl."/".$this->controller."/".$this->action."/page/1$filtoptions'><<</a>";
$html .= "<a class='pagination_lnk' href='".$this->baseUrl."/".$this->controller."/".$this->action."/page/".($this->current_page - 1)."$filtoptions'><</a>";
}
for($i=1;$i<=$this->number_of_pages;$i++){
if( $i == $this->current_page ){
$html .= "<a class='active pagination_lnk' href='".$this->baseUrl."/".$this->controller."/".$this->action."/page/".$i."$filtoptions'>".$i."</a>";
}else{
$html .= "<a class='pagination_lnk' href='".$this->baseUrl."/".$this->controller."/".$this->action."/page/".$i."$filtoptions'>".$i."</a>";
}
}
if( $this->current_page != $this->number_of_pages ){
$html .= "<a class='pagination_lnk' href='".$this->baseUrl."/".$this->controller."/".$this->action."/page/".($this->current_page + 1)."$filtoptions'>></a>";
$html .= "<a class='pagination_lnk' href='".$this->baseUrl."/".$this->controller."/".$this->action."/page/".$this->number_of_pages."$filtoptions'>>></a>";
}
$html .= "<div>";
}
/* End of pagination */
$html .= "<div class='clear'></div>";
$html .= "</div>";
$html .= "</td>";
$html .= "</tr>";
/* End Of Page Numbers */
$html .= "</table>";
}
$this->view->grid = $html;
}
private function getHeaderCols(){
$cols = array();
if( !empty($this->item_data) ){
foreach($this->item_data as $key=>$itemd){
foreach( $itemd as $c=>$d ){
if( !in_array($c, array('item_d_count')) && !in_array($c, $cols) ){
$cols[] = $c;
}
}
}
}
$this->col_list = $cols;
if( !empty($this->column_names) && !empty($cols) ){
foreach( $this->column_names as $colname=>$value ){
if( in_array($colname, $cols) ){
foreach( $cols as $ckey=>$cdata ){
if( $cdata == $colname ){
$cols[$ckey] = $value;
}
}
}
}
}
return $cols;
}
public function setDeleteButton($status = 0, $controller = '', $action = ''){
if( in_array(intval($status), array(1)) ){
$this->delete_button_enabled = 1;
$this->delete_button_controller = $controller;
$this->delete_button_action = $action;
}
}
public function setEditButton($status = 0, $controller = '', $action = ''){
if( in_array(intval($status), array(1)) ){
$this->edit_button_enabled = 1;
$this->edit_button_controller = $controller;
$this->edit_button_action = $action;
}
}
}
?>
After that i pass parameters to Datagrid.php in my IndexController index action. Off course you can use any controller and any action, it only depends in you.
public function indexAction() {
/* Datagrid params */
$page = $this->_request->getParam('page',1);
$step = $this->_request->getParam('step',20);
$order = $this->_request->getParam('order');
$orderdir = $this->_request->getParam('orderdir','ASC');
/* End of Datagrid params*/
/* Sql for datagrid */
/* The Zend_Db_Expr is very important, because it calculates the number of items without page/step limitations ( in a faster way ) and it need to be there in every Zend sql query */
$select = $this->db->select()
->from(array("u" => "user"), array(new Zend_Db_Expr('SQL_CALC_FOUND_ROWS u.id as item_d_count'),"id", "username", "email", "created", "modified", "enabled"))
->join(array("ur" => "user_role"), "u.id = ur.user_id", array("role_id"))
->join(array("r" => "role"), "ur.role_id = r.id", array("role as role_title"))
->where("u.deleted='0'");
/* End of sql for datagrid */
$datagrid = new Datagrid($this->view);
$datagrid->setDeleteButton(1,'admin','delete'); // Status, Controller, Action
$datagrid->setEditButton(1,'admin','editadmin'); // Status, Controller, Action
$datagrid->setParams($page,$step, $order, $orderdir); // page, step, order, orderdir
$datagrid->column_names = array("id" => "Field id", "role_title" => "Role"); // Field => New filed title
$datagrid->class_array = array("id" => "textCenter", "role_title" => "textCenter", "enabled" => "textCenter"); // Field => class or class list ("textCenter textBold")
$datagrid->generateZendSql($select);
/* Example how to use datagrid with multi dimensional array's */
$dataArray = array(
0 => array('id' => 1,
'enabled' => 0,
'name' => 'Lorem ipsum 1',
'title' => 'aaaa'
),
1 => array('id' => 2,
'enabled' => 1,
'name' => 'Lorem ipsum 2',
'title' => ''
),
2 => array('id' => 3,
'enabled' => 1,
'name' => 'Lorem ipsum 3',
'title' => ''
),
3 => array('id' => 4,
'enabled' => 0,
'name' => 'Lorem ipsum 4',
'title' => ''
)
);
$datagrid->generateArray($dataArray);
/*------------------------------------------ */
}
In your phtml file you need to add the following code ( i added to my index/index.phtml file because i used index controller and index action ):
The basic css file is look like this for me:
table.grid {
width: 100%;
margin: 15px 0px 40px 0px;
}
table.grid img.order_img {
margin: 0px 5px 0px 5px;
}
table.grid tr.grid_head_tr {
background-color: #2A2A2A;
color: #FFF;
}
table.grid td.grid_head_td {
border-right: 1px solid #fff;
text-align: center;
padding: 12px 5px 12px 5px;
}
div.fl {
float: left;
}
div.fr {
float: right;
}
table.grid tr.grid_footer_tr {
}
table.grid tr td.grid_footer_td {
padding-top: 20px;
border-top: 1px solid #2A2A2A;
}
table.grid td.content {
padding: 10px 5px 10px 5px;
}
table.grid a.pagination_lnk {
margin: 0px 6px 0px 6px;
text-decoration: none;
}
table.grid a.pagination_lnk:hover, table.grid a.active {
text-decoration: underline;
}
.textCenter {
text-align: center;
}
.textLeft {
text-align: left;
}
.textRight {
text-align: right;
}
table.grid input.grid_submit_btn {
border: 1px solid #2A2A2A;
background-color: #FFF;
color: #2A2A2A;
}
table.grid tr.alt {
background-color: #eee;
}
width: 100%;
margin: 15px 0px 40px 0px;
}
table.grid img.order_img {
margin: 0px 5px 0px 5px;
}
table.grid tr.grid_head_tr {
background-color: #2A2A2A;
color: #FFF;
}
table.grid td.grid_head_td {
border-right: 1px solid #fff;
text-align: center;
padding: 12px 5px 12px 5px;
}
div.fl {
float: left;
}
div.fr {
float: right;
}
table.grid tr.grid_footer_tr {
}
table.grid tr td.grid_footer_td {
padding-top: 20px;
border-top: 1px solid #2A2A2A;
}
table.grid td.content {
padding: 10px 5px 10px 5px;
}
table.grid a.pagination_lnk {
margin: 0px 6px 0px 6px;
text-decoration: none;
}
table.grid a.pagination_lnk:hover, table.grid a.active {
text-decoration: underline;
}
.textCenter {
text-align: center;
}
.textLeft {
text-align: left;
}
.textRight {
text-align: right;
}
table.grid input.grid_submit_btn {
border: 1px solid #2A2A2A;
background-color: #FFF;
color: #2A2A2A;
}
table.grid tr.alt {
background-color: #eee;
}
I used the following images:
Jqyery & Plugins you may want to use:
You can download the latest jquery from here : http://jquery.com/
The tipsy jquery plugin is not necessary. If you want to add than you can download the plugin here: http://onehackoranother.com/projects/jquery/tipsy/
If you added the tippsy plugin then you need to add the following jquery to your view file or into your layout.phtml:
<script type="text/javascript">
$(document).ready(function(){
$(".tippsy").tipsy();
});
</script>What is apprise?
An alert alternative for jQuery that looks good. Apprise is a very simple, fast, attractive, and unobtrusive way to communicate with your users.
You can download apprise plugin here: http://thrivingkings.com/apprise/
So, this is my current version of datagrid. I didn't finished everything yet, but in the future i plan to add more functionalities. But I think you can use some of functionalities in your project, or you can use the whole Datagrid system if you like it.
Functionalities i want to add in the future:
- Order of fields in table header
- Export to pdf with csv, tcpdf
- Special filed values ( or replaceing field values with images ) depending on filed values ( like enable/disable fileds or created/modified etc ... )
No comments:
Post a Comment