<?php
/* vim: set number autoindent tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* This package add combobox type to HTML_QuickForm
*
* A combobox is an element composed by an input text and a dropdown list:
* you can either select an option from the list or write into the text field.
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to hide@address.com so we can mail you a copy immediately.
*
* @category HTML
* @package HTML_QuickForm_ComboBox
* @author Fabio Ambrosanio <hide@address.com>
* @license http://www.php.net/license/3_01.txt PHP
* @version @package_version@
*
* $Id: combobox.php,v 1.2 2006/11/29 21:14:39 fabamb Exp $
*/
require_once 'HTML/QuickForm/text.php';
/**
* This class represents a combobox element of HTML_QuickForm framework.
*
* @author Fabio Ambrosanio <hide@address.com>
* @category HTML
* @package HTML_QuickForm_ComboBox
* @version @package_version@
* @license http://www.php.net/license/3_01.txt PHP
*/
class HTML_QuickForm_ComboBox extends HTML_QuickForm_text
{
// {{{ properties
/**
* Elements of the dropdown list
*
* @var array
* @access private
*/
var $_elements = null;
/**
* Filename of css stylesheet
*
* @var string
*/
var $_css = 'combobox.css';
/**
* Path of css stylesheet
*
* @var unknown_type
*/
var $_css_path = false;
/**
* Filename and path of javascript library
*/
var $_js = 'combobox.js';
/**
* Options for element's UI.
* You can modify the appearence of combobox (see below for the list of elements and classes.
*
* If options contains a value for arrowImage key, an image is used instead of a button.
*
* @var array
* @access private
*/
var $_options = array(
'boxClass' => 'comboBox', // style class of external box
'inputClass' => 'comboBoxInput', // style class of input text field
'buttonClass' => 'comboBoxButton', // style class of dropdown button
'arrowClass' => 'comboBoxArrow', // style class of dropdown image
'containerClass' => 'comboBoxContainer', // style class of dropdown container
'optionClass' => 'comboBoxOption', // style class of dropdown options
'optionClassOver' => 'comboBoxOptionOver', // style class of dropdown options when highlighted
'buttonValue' => '*' // value of dropdown button
);
// }}}
// {{{ constructor
/**
* Class constructor
*
* @param string $elementName (required)Input field name attribute.
* @param string $elementLabel (required)Input field label in form.
* @param array $elements (optional)Combobox elements.
* @param array $options (optional)An associative array which elements specify different
* aspects of the combobox.
* @param mixed $attributes (optional)Either a typical HTML attribute string
* or an associative array. Date format is passed along the attributes.
* @access public
* @return void
*
* With $options you can specify the CSS class to use with different aspects of the combobox.
* The compobox's aspects that you can change assigning different CSS class are:
* <pre>
* Aspect Description Default class
* boxClass external box comboBox
* inputClass input textfield comboBoxInput
* buttonClass dropdown button (if used) comboBoxButton
* arrowClass dropdown arrow (if used) comboBoxArrow
* containerClass dropdown container comboBoxContainer
* optionClass single option inside dropdown container comboBoxOption
* optionClassOver single option when mouse is over comboBoxOptionOver
* </pre>
*
* You can change the button (value)label with buttonValue option, es.: butonValue => 'V' or
* specify images to use to render the button:
* <pre>
* arrowImage image used to render the button in normal state
* arrowImageOver image used when the mouse is over the button
* arrowImageDown image used when the button in clicked
* </pre>
*/
function HTML_QuickForm_ComboBox($elementName = null, $elementLabel = null, $elements = null, $options = null, $attributes = null)
{
$this->HTML_QuickForm_text($elementName, $elementLabel, $attributes);
$this->_persistantFreeze = true;
if (isset($elements)) {
$this->_elements = $elements;
}
$id = $this->getAttribute('id');
if ("$id" == '') {
$this->updateAttributes(array(
'id' => $elementName
));
}
// update element options
if ($options && is_array($options)) {
$this->_options = array_merge($this->_options, $options);
}
} //end constructor
// }}}
// {{{ toHtml()
/**
* Returns Html for the Combobox input element
*
* @access public
* @return string the HTML string representing the combobox
*/
function toHtml()
{
// generate an unique id for all UI elements
$uid = uniqid('cb');
if ($this->_flagFrozen) {
// input froze: return parent html
$html = parent::toHtml();
} else {
// eventually write style classes and javascript functions
$html = $this->_getCSS();
$html .= $this->_getJS();
// build input text field
$this->updateAttributes(array(
'class' => $this->_options['inputClass']
));
$input = parent::toHtml();
// wich type of button? input-button or image?
if (!$this->_options['arrowImage']) {
// build simple button
$buttonClass = $this->_options['buttonClass'];
$buttonValue = $this->_options['buttonValue'];
$button = "<input value=\"$buttonValue\" type=\"button\" id=\"$uid.button\" class=\"$buttonClass\" onClick=\"comboBoxShowOptions('$uid')\" onblur=\"comboBoxHideOptions('$uid')\"/>";
} else {
// build button implemented with an image
$arrowImage = $this->_options['arrowImage'];
// have we an image for mouse-over?
$arrowImageOver = $this->_options['arrowImageOver'];
if (!$arrowImageOver) $arrowImageOver = $arrowImage;
// have we an image for mouse-down?
$arrowImageDown = $this->_options['arrowImageDown'];
if (!$arrowImageDown) $arrowImageDown = $arrowImage;
$arrowClass = $this->_options['arrowClass'];
$button = "<input type=\"image\" src=\"$arrowImage\" id=\"$uid.arrow\" class=\"$arrowClass\" align=\"top\" onClick=\"comboBoxShowOptions('$uid'); return false;\" onMouseOver=\"comboBoxSwitchImage('$uid')\" onMouseOut=\"comboBoxSwitchImage('$uid')\" arrowimage=\"$arrowImage\" arrowimageover=\"$arrowImageOver\" arrowimagedown=\"$arrowImageDown\" onblur=\"comboBoxHideOptions('$uid')\" />";
}
// build elements list
$options = '';
if (is_array($this->_elements)) {
$optionClass = $this->_options['optionClass'];
if ($this->_is_assoc_array($this->_elements)) {
foreach ($this->_elements as $k => $e) {
$options .= "<div class=\"$optionClass\" width=\"500px\" value=\"$k\">$e</div>";
}
} else {
foreach ($this->_elements as $e) {
$options .= "<div class=\"$optionClass\" width=\"500px\">$e</div>";
}
}
}
// build the whole combobox
$boxClass = $this->_options['boxClass'];
$containerClass = $this->_options['containerClass'];
$html .= "<div id=\"$uid.box\" class=\"$boxClass\" width=\"500px\">$input$button</div><div id=\"$uid.container\" class=\"$containerClass\" width=\"500px\">$options</div>";
// add this combobox to a javascript array:
// when the page is loaded a script will resize each combobox
$html .= "<script type=\"text/javascript\">var aCombo = new Object();aCombo[\"id\"] = '$uid';combos[combos.length++] = aCombo;</script>";
}
return $html;
}// end func toHtml
// }}}
// {{{ setCSS($filename, $path)
/**
* Sets new CSS file
*
* @param string $filename filename of CSS file
* @param string $path path of CSS file
* @param string $options associative array which elements specify CSS classes for different aspects cf the combobox
*/
function setCSS($filename, $path = false, $options = false)
{
$this->_css = $filename;
$this->_css_path = $path;
if ($options && is_array($options)) {
$this->_options = array_merge($this->_options, $options);
}
}// end func setCSS
// }}}
/**
* Returns CSS styles
*
* @return string
* @access private
*/
function _getCSS()
{
if (defined('HTML_QUICKFORM_COMBOBOX_CSS_' . $this->_css_path . $this->_css)) return '';
define('HTML_QUICKFORM_COMBOBOX_CSS_' . $this->_css_path . $this->_css, true);
$location = $this->_getFileLocation($this->_css, $this->_css_path);
$css = "<style type=\"text/css\">";
$css .= "/* "; if ($this->_css_path) $css .= $this->_css_path . DIRECTORY_SEPARATOR;
$css .= $this->_css . " */";
$css .= file_get_contents($location) . "</style>";
return $css;
}
/**
* Returns javascript functions
*
* @return string
* @access private
*/
function _getJS()
{
if (defined('HTML_QUICKFORM_COMBOBOX_JS')) return '';
define('HTML_QUICKFORM_COMBOBOX_JS', true);
$location = $this->_getFileLocation($this->_js, false);
$js = "<script type=\"text/javascript\">" . file_get_contents($location) . "</script>";
return $js;
}
/**
* Calcs the canonical path of the specified file
*
* @param string $filename
* @param string $path
* @return string
*/
function _getFileLocation($filename, $path)
{
if ($path) {
$location = realpath($path . DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $filename;
} else {
$path = '@data-dir@'.DIRECTORY_SEPARATOR.'HTML_QuickForm_ComboBox'.DIRECTORY_SEPARATOR;
if(strpos($path, '@'.'data-dir@') === 0) {
$path = realpath(dirname(__FILE__).DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
}
$location = $path.$filename;
}
return $location;
}
/**
* Checks if an array is associative
*
* @param array $php_val
* @return true if $php_val is an associative array, false otherwise
*/
function _is_assoc_array( $php_val )
{
if( !is_array( $php_val ) ){
# Neither an associative, nor non-associative array.
return false;
}
$given_keys = array_keys( $php_val );
$non_assoc_keys = range( 0, count( $php_val ) );
if ( function_exists( 'array_diff_assoc' ) ) { # PHP > 4.3.0
return array_diff_assoc( $given_keys, $non_assoc_keys );
} else {
return array_diff( $given_keys, $non_assoc_keys ) and array_diff( $non_assoc_keys, $given_keys );
}
}
} // end class HTML_QuickForm_ComboBox
if (class_exists('HTML_QuickForm')) {
HTML_QuickForm::registerElementType('combobox', 'HTML/QuickForm/combobox.php', 'HTML_QuickForm_ComboBox');
}
?>