1<?php
2/* vim: set number autoindent tabstop=2 shiftwidth=2 softtabstop=2: */
3// +----------------------------------------------------------------------+
4// | PHP Version 4                                                        |
5// +----------------------------------------------------------------------+
6// | This source file is subject to version 3.0 of the PHP license,       |
7// | that is bundled with this package in the file LICENSE, and is        |
8// | available at through the world-wide-web at                           |
9// | http://www.php.net/license/3_0.txt                                   |
10// | If you did not receive a copy of the PHP license and are unable to   |
11// | obtain it through the world-wide-web, please send a note to          |
12// | license@php.net so we can mail you a copy immediately.               |
13// +----------------------------------------------------------------------+
14// | Author:  Giuseppe Dessì <thesee@fastwebnet.it>                       |
15// +----------------------------------------------------------------------+
16// $Id$
17
18/**
19 * Class to dynamically create an HTML input text element that
20 * at every keypressed javascript event, call by XMLHttpRequest for sending
21 * the request to the server. A PHP script or XML or a static file returns
22 * a response in a arbitrary format, depending on the our needed.
23 * We can see the data on a live dropdown select
24 *
25 * @author       Giuseppe Dessì <thesee@fastwebnet.it>
26 */
27require_once 'HTML/QuickForm/text.php';
28
29class HTML_QuickForm_LiveSearch_Select extends HTML_QuickForm_text
30{
31    // {{{ properties
32
33     /**
34     * Options for the LiveSearch_Select input text element
35     *
36     * @var       array
37     * @access    private
38     */
39    var $_options = array();
40
41    /**
42     * Original name of element
43     *
44     * @var       string
45     * @access    private
46     */
47    var $realName = '';
48
49    /**
50     * The values passed by the hidden element
51     *
52     * @var array
53     * @access private
54     */
55    var $_value = null;
56    var $_hidden_value = null;
57
58    // }}}
59    // {{{ constructor
60
61    /**
62     * Class constructor
63     *
64     * @param     string    $elementName    (required)Input field name attribute
65     * @param     string    $elementLabel   (required)Input field label in form
66     * @param     array     $options        (optional)LiveSearch_Select options
67     * @param     mixed     $attributes     (optional)Either a typical HTML attribute string
68     *                                      or an associative array. Date format is passed along the attributes.
69     * @access    public
70     * @return    void
71     */
72    function HTML_QuickForm_LiveSearch_Select($elementName = null, $elementLabel = null, $options = null, $attributes = null)
73    {
74        $this->HTML_QuickForm_text($elementName, $elementLabel, $attributes);
75        $this->_persistantFreeze = true;
76        $this->_type = 'livesearch_select';
77        if (isset($options)) {
78            $this->setOptions($options);
79        }
80    } //end constructor
81    /**
82     * Gets the private name for the element
83     *
84     * @param   string  $elementName The element name to make private
85     *
86     * @access public
87     * @return string
88     */
89    function getPrivateName($elementName)
90    {
91        return 'q'.$elementName;
92    }
93    // }}}
94    // {{{ setOptions()
95
96    /**
97     * Sets the element's value
98     *
99     * @param    mixed   Element's value
100     * @access   public
101     */
102    function setValue($value)
103    {
104        $this->_hidden_value = $value;
105        if (isset($this->_options['callback']) AND is_callable($this->_options['callback']) ) {
106            if (isset($this->_options['dbh']) ) {
107                $dbh = $this->_options['dbh'];
108            } else {
109                $dbh = NULL;
110            }
111            $this->_value = call_user_func($this->_options['callback'], $dbh, $value);
112            $this->updateAttributes(array(
113                                        'value' => $this->_value
114                                        )
115                                    );
116        } else {
117            $this->updateAttributes(array(
118                                        'value' => $value
119                                        )
120                                    );
121        }
122    }
123    /**
124     * Gets the element's value
125     *
126     * @param    mixed   Element's value
127     * @access   public
128     */
129    function getValue($internal = NULL)
130    {
131        if ($this->_flagFrozen) {
132            if ($internal) {
133                return $this->_value;
134            } else {
135                return $this->_hidden_value;
136            }
137        } else {
138            return $this->_hidden_value;
139        }
140    }
141    /**
142     * Sets the options for the LiveSearch_Select input text element
143     *
144     * @param     array    $options    Array of options for the LiveSearch_Select input text element
145     * @access    public
146     * @return    void
147     */
148    function setOptions($options)
149    {
150        $this->_options = $options;
151    } // end func setOptions
152
153    // }}}
154    // {{{ getFrozenHtml()
155
156    /**
157     * Returns the value of field without HTML tags
158     *
159     * @since     1.0
160     * @access    public
161     * @return    string
162     */
163    function getFrozenHtml()
164    {
165        $value = $this->getValue(true);
166        $id = $this->getAttribute('id');
167        return ('' != $value ? htmlspecialchars($value): '&nbsp;').'<input' . $this->_getAttrString(array(
168                       'type'  => 'hidden',
169                       'name'  => $this->realName,
170                       'value' => $this->getValue()
171                   ) + (isset($id)? array('id' => $id): array())) . ' />';
172    } //end func getFrozenHtml
173
174    // }}}
175    // {{{ toHtml()
176    /**
177     * Returns Html for the LiveSearch_Select input text element
178     *
179     * @access      public
180     * @return      string
181     */
182    function toHtml()
183    {
184        $this->realName = $this->getName();
185        $liveform = '';
186        $scriptLoad = '';
187        $style = 'display: block;';
188        $divstyle = ' class="divstyle" ';
189        $ulstyle = ' class="ulstyle" ';
190        $listyle = ' class="listyle" ';
191        $zeroLength = 0;
192        $printStyle = 1;
193        $this->updateAttributes(array(
194                                      'name' => $this->getPrivateName($this->realName)
195                                     )
196                                );
197        if (isset($this->_options['style']) AND $this->_options['style'] != '') {
198            $style = $this->_options['style'];
199        }
200        if (isset($this->_options['divstyle']) AND $this->_options['divstyle'] != '') {
201            $divstyle =  ' class="'.$this->_options['divstyle'].'" ';
202        }
203        if (isset($this->_options['ulstyle']) AND $this->_options['ulstyle'] != '') {
204            $ulstyle =  ' class="'.$this->_options['ulstyle'].'" ';
205        }
206        if (isset($this->_options['listyle']) AND $this->_options['listyle'] != '') {
207            $listyle =  ' class="'.$this->_options['listyle'].'" ';
208        }
209        if (isset($this->_options['searchZeroLength']) AND $this->_options['searchZeroLength'] == 1) {
210            $zeroLength = 1;
211        } else {
212            $zeroLength = 0;
213        }
214        if (isset($this->_options['printStyle']) AND $this->_options['printStyle'] != 1) {
215            $printStyle = 0;
216        }
217        if (isset($this->_options['autoserverPath']) AND $this->_options['autoserverPath'] != '') {
218            $autoserverPath = $this->_options['autoserverPath'];
219        } else {
220            $autoserverPath = '';
221        }
222        if (isset($this->_options['autoComplete']) AND $this->_options['autoComplete'] != 0) {
223            $this->updateAttributes(array(
224                                        'autocomplete' => 'off'
225                                        )
226                                    );
227        }
228        $this->updateAttributes(array(
229                                      'onkeyup' => 'javascript:liveSearchKeyPress(this, event, \''.$this->getName().'Result\', \'target_'.$this->_options['elementId'].'\', \''.$this->_options['elementId'].'\', \''.$this->realName.'\', '.$zeroLength.');',//'javascript:'.$this->getName().'ObjLS.liveSearchKeyPress(this, event);disable();',
230                                      'onblur' => 'javascript:liveSearchHide(\''.$this->getName().'Result\');',
231                                      'id' => $this->_options['elementId'],
232                                      'style' => $style
233                                      )
234                               );
235        if ($this->_flagFrozen) {
236            return $this->getFrozenHtml();
237        } else {
238            $liveform .= '
239<div'.$divstyle.'id="'.$this->getName().'Result">
240    <ul'.$ulstyle.'id="target_'.$this->_options['elementId'].'">
241        <li'.$listyle.'>&nbsp;</li>
242    </ul>
243</div>';
244            if (!defined('HTML_QUICKFORM_LIVESEARCH_EXISTS')) {
245                if ($printStyle != 0) {
246                    $scriptLoad = <<<EOS
247<style type="text/css">
248<!--
249.divstyle {
250    position: absolute;
251    background-color: #aaa;
252    z-index: 1;
253    min-width: 140px;
254    float:left;
255    clear:left;
256    background: url(shadowAlpha.png) no-repeat bottom right !important;
257    background: url(shadow.gif) no-repeat bottom right;
258    margin: 10px 0 10px 10px !important;
259    padding: 0px;
260    display: none;
261}
262* html .divstyle { width: 140px;}
263.ulstyle {
264    list-style-type: none;
265    position: relative;
266    right: 0px;
267    z-index: 1;
268    margin: 0px;
269    padding: 0px;
270}
271
272.listyle {
273    text-indent: -20px;
274    z-index: 1;
275    padding-right: 15px;
276    padding-bottom: 2px;
277    padding-top: 2px;
278    padding-left: 20px;
279    line-height:15px;
280    margin-bottom: 0px;
281}
282.outerUl {
283    list-style-type: none;
284    position: relative;
285    z-index: 1;
286    background-color: #FFFFFF;
287    color: inherit;
288    bottom:6px;
289    right: 6px;
290    border: 1px solid #999999;
291    text-indent: -20px;
292    margin: 0px;
293    padding: 0px;
294}
295.outerLi {
296    text-indent: -20px;
297    z-index: 1;
298    padding: 2px 15px 2px 20px;
299    line-height:15px;
300    margin-bottom: 0px;
301}
302-->
303</style>
304EOS;
305                }
306                $scriptLoad .= <<<EOS
307<script type='text/javascript' src="{$autoserverPath}auto_server.php?client=Util,main,dispatcher,httpclient,request,json,loading,queues,QfLiveSearch&amp;stub=livesearch"></script>
308<script type='text/javascript'>//<![CDATA[
309callback = {};
310function searchRequest(searchBox, callfunc) {
311    eval("remoteLiveSearch."+callfunc+"(searchBox.value)");
312}
313//]]>
314</script>
315
316EOS;
317
318                define('HTML_QUICKFORM_LIVESEARCH_EXISTS', true);
319            }
320            $scriptLoad .= '
321<script type="text/javascript">//<![CDATA[
322callback.'.$this->_options['elementId'].' = function(result) {
323    var  res = document.getElementById(\''.$this->getName().'Result\');
324    res.style.display = "block";
325    var out = "<ul class=\"outerUl\" >";
326    for(var i in result) {
327        if (i != \'______array\') {
328            out += "<li class=\"outerLi\"><a href=\"#\" value=\""+i+"\" text=\""+result[i]+"\" onmouseover=\"liveSearchHover(this);\" onmousedown=\"liveSearchClicked(this.getAttribute(\'value\'), this.getAttribute(\'text\'), \''.$this->_options['elementId'].'\', \''.$this->realName.'\');\">"+result[i]+"<\/a><\/li>";
329        }
330    }
331    out += "<\/ul>";
332    document.getElementById(\'target_'.$this->_options['elementId'].'\').innerHTML = out;
333}
334//]]>
335</script>
336
337';
338                    if (!defined('HTML_QUICKFORM_JS_INIT_EXISTS')) {
339                        $scriptLoad .= '
340
341<script type="text/javascript">//<![CDATA[
342    var remoteLiveSearch = new livesearch(callback);
343    remoteLiveSearch.dispatcher.queue = \'rls\';
344    HTML_AJAX.queues[\'rls\'] = new HTML_AJAX_Queue_Interval_SingleBuffer('.(int)$this->_options['buffer'].');
345//]]>
346</script>
347';
348                        define('HTML_QUICKFORM_JS_INIT_EXISTS', true);
349                    }
350            $scriptLoad .= '
351<input type="hidden" name="'.$this->realName.'" id="'.$this->realName.'" value="'.$this->_hidden_value.'" />'."\n";
352
353
354        }
355    return $scriptLoad.parent::toHtml().$liveform;
356    }// end func toHtml
357
358    // }}}
359} // end class HTML_QuickForm_LiveSearch_Select
360if (class_exists('HTML_QuickForm')) {
361    HTML_QuickForm::registerElementType('livesearch_select', 'HTML/QuickForm/livesearch_select.php', 'HTML_QuickForm_LiveSearch_Select');
362}
363?>
364