Code

b87136c612f27a00d41ea01159de3103bd41fe90
[gosa.git] / gosa-core / include / class_sortableListing.inc
1 <?php
2 /*
3  * This code is part of GOsa (http://www.gosa-project.org)
4  * Copyright (C) 2003-2008 GONICUS GmbH
5  *
6  * ID: $$Id: class_listing.inc 15087 2010-01-06 13:45:49Z hickert $$
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
23 class sortableListing {
24   private $header= null;
25   private $colspecs= null;
26   private $reorderable= true;
27   private $width= "400px";
28   private $height= "100px";
29   private $cssclass= "";
30   private $id;
32   private $data= array();
33   private $columns= 0;
34   private $deleteable= false;
35   private $editable= false;
36   private $instantDelete= true;
37   private $action;
38   private $targets;
39   private $mapping;
40   private $current_mapping;
41   private $active_index;
43   function sortableListing($data= array())
44   {
45     global $config;
47     // Save data to display
48     $this->setData($data);
50     // Generate instance wide unique ID
51     $tmp= gettimeofday();
52     $this->id= 'l'.md5($tmp['sec']);
53   }
56   function setData($data)
57   {
58     if (!is_array($data)) {
59       die ("sortableList needs an array as data!");
60     }
62     // Transfer information
63     $this->data= $data;
65     // Create initial mapping
66     $this->mapping= array_keys($data);
68     // Find the number of coluns
69     reset($this->data);
70     $first= current($this->data);
71     if (is_array($first)) {
72       $this->columns= count($first);
73     } else {
74       $this->columns= 1;
75     }
76   }
79   function setWidth($width)
80   {
81     $this->width= $width;
82   }
85   function setInstantDelete($flag)
86   {
87     $this->instantDelete= $flag;
88   }
91   function setEditable($flag)
92   {
93     $this->editable= $flag;
94   }
97   function setDeleteable($flag)
98   {
99     $this->deleteable= $flag;
100   }
103   function setHeight($height)
104   {
105     $this->height= $height;
106   }
109   function setCssClass($css)
110   {
111     $this->cssclass= $css;
112   }
115   function setHeader($header)
116   {
117     $this->header= $header;
118   }
121   function setColspecs($specs)
122   {
123     $this->colspecs= $specs;
124   }
127   function render()
128   {
129     $result= "<div class='sortableListContainer' id='scroll_".$this->id."' style='width: ".$this->width."; height: ".$this->height."'>\n";
130     $result.= "<table border='0' cellpadding='0' cellspacing='0' width='100%' height='100%' style='position: relative;'".(!empty($this->cssclass)?" class='".$this->cssclass."'":"").">\n";
131     $action_width= 0;
132     $edit_image= $this->editable?"<input class='center' type='image' src='images/lists/edit.png' alt='"._("Edit")."' name='%ID' title='"._("Edit this entry")."'>":"";
133     $delete_image= $this->deleteable?"<input class='center' type='image' src='images/lists/trash.png' alt='"._("Delete")."' name='%ID' title='"._("Delete this entry")."'>":"";
135     // Do we need colspecs?
136     $action_width= ($this->editable?20:0) + ($this->deleteable?20:0);
137     if ($this->colspecs) {
138       $result.= " <colgroup>\n";
139       for ($i= 0; $i<$this->columns; $i++) {
140         $result.= "  <col width='".(isset($this->colspecs[$i])?$this->colspecs[$i]:"*")."'/>\n";
141       }
143       // Extend by another column if we've actions specified
144       if ($action_width) {
145         $result.= "  <col width='$action_width'/>\n";
146       }
147       $result.= " </colgroup>\n";
148     }
150     // Do we need a header?
151     if ($this->header) {
152       $result.= " <thead>\n  <tr>\n";
153       for ($i= 0; $i<$this->columns; $i++) {
154         $result.= "   <th>".(isset($this->header[$i])?$this->header[$i]:"")."</th>";
155       }
156       if ($action_width) {
157         $result.= "<th>&nbsp;</th>";
158       }
159       $result.= "\n  </tr>\n </thead>\n";
160     }
162     // Render table body
163     $result.= " <tbody id='".$this->id."'>\n";
164     foreach ($this->mapping as $nr => $row) {
165       $result.= "  <tr class='sortableListItem".($nr&1?'Odd':'')."' id='item_".$this->id."_$nr'>\n";
166       foreach ($this->data[$row] as $column) {
167         $result.= "   <td>".htmlentities($column)."</td>\n";
168       }
169       if ($action_width) {
170         $result.= "<td>".str_replace('%ID', "edit_".$this->id."_$nr", $edit_image).
171                          str_replace('%ID', "del_".$this->id."_$nr", $delete_image)."</td>";
172       }
173       $result.= "  </tr>\n";
174     }
176     $result.= " </tbody>\n</table>\n</div>\n";
177     $result.= " <input type='hidden' name='reorder_".$this->id."' id='reorder_".$this->id."'>\n";
179     // Append script stuff if needed
180     $result.= '<script type="text/javascript" language="javascript">';
181     $result.= ' function updateOrder(){';
182     $result.= '    var ampcharcode= \'%26\';';
183     $result.= '    var serializeOpts = Sortable.serialize(\''.$this->id.'\')+"='.$this->id.'";';
184     $result.= '    $("reorder_'.$this->id.'").value= serializeOpts;';
185     $result.= '    document.mainform.submit();';
186     $result.= ' }';
187     $result.= 'Position.includeScrollOffsets = true;';
188     $result.= ' Sortable.create(\''.$this->id.'\',{tag:\'tr\', ghosting:false,constraint:\'vertical\', scroll:\'scroll_'.$this->id.'\',onUpdate : updateOrder})';
189     $result.= '</script>';
191     return $result;
192   }
195   function update()
196   {
197     // Do not do anything if we're not posted
198     if (isset($_POST['reorder_'.$this->id])){
200       // Move requested?
201       $move= $_POST['reorder_'.$this->id];
202       if ($move != "") {
203         preg_match_all('/=([0-9]+)[&=]/', $move, $matches);
204         $this->action= "reorder";
205         $tmp= array();
206         foreach ($matches[1] as $id => $row) {
207           $tmp[$id]= $this->mapping[$row];
208         }
209         $this->mapping= $tmp;
210         $this->current_mapping= $matches[1];
211         return;
212       }
214       // Delete requested?
215       foreach ($_POST as $key => $value) {
216         if (preg_match('/^del_'.$this->id.'_([0-9]+)_x.*$/', $key, $matches)) {
217           $this->active_index= $this->mapping[$matches[1]];
218           $this->action= "delete";
219           if ($this->instantDelete) {
220             $this->deleteEntry($this->active_index);
221           }
222         }
223       }
225       // Edit requested?
226       foreach ($_POST as $key => $value) {
227         if (preg_match('/^edit_'.$this->id.'_([0-9]+)_x.*$/', $key, $matches)) {
228           $this->active_index= $this->mapping[$matches[1]];
229           $this->action= "edit";
230         }
231       }
233     }
234   }
237   function getAction()
238   {
239     // Do not do anything if we're not posted
240     if(!isset($_POST['reorder_'.$this->id])) {
241       return;
242     }
244     // For reordering, return current mapping
245     if ($this->action == 'reorder') {
246       return array("targets" => $this->current_mapping, "mapping" => $this->mapping, "action" => $this->action);
247     }
249     // Edit and delete
250     $result= array("targets" => array($this->active_index), "action" => $this->action);
252     return $result;
253   }
256   function deleteEntry($id)
257   {
258     $index= array_search($id, $this->mapping);
259     if ($index !== false) {
260       unset($this->mapping[$index]);
261       $this->mappings= array_values($this->mappings);
262     }
263   }