<?php
    //========================================================================================================================
    /**
     * DOMエレメント拡張コンポーネントクラス
     *
     * LICENSE: This source file is subject to GNU GENERAL PUBLIC LICENSE Version 3
     * http://www.gnu.org/licenses/gpl-3.0.txt.
     *
     * @package    LabbitBox
     * @subpackage core
     * @copyright  2010 LabbitBox Development Team.
     * @license    GPL v3 http://www.gnu.org/licenses/gpl-3.0.txt
     * @author     neobaba <neobaba@labbitbox.org>
     * @version    v0.1
     * @since      2010/2/26
     * @link       http://labbitbox.org/
     * @see        http://labbitbox.org/
     */
    //========================================================================================================================
    require_once(BASE_LIB.'/HtmlElement.php');

    //========================================================================================================================
    /**
     * 拡張コンポーネント基底クラス
     */
    //========================================================================================================================
    abstract class Components extends HtmlElement{
        public function __construct($elementID, $tagName){
            parent::__construct($elementID, $tagName);
        }

        public function append($parent, $containerID = NULL){
            $parent->appendElement($this, $containerID);
            $this->mount($parent, $containerID);
        }

        public function displace($parent, $containerID = NULL){
            $parent->displaceElement($this, $containerID);
            $this->mount($parent, $containerID);
        }

        public function replace($parent, $containerID = NULL){
            $parent->replaceElement($this, $containerID);
            $this->mount($parent, $containerID);
        }

        protected function mount($parent, $containerID = NULL){

        }
    }
    
    //========================================================================================================================
    /**
     * selectタグ系コンポーネント基底クラス
     */
    //========================================================================================================================
    class Select extends Components{
        private $_options = array();
    
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * コンストラクタ
         * @param object    $elementID      エレメントID
         * @param array     $datasource     データーソース：value値 => 表示文字列 の連想配列
         * @param array     $config         表示フォーマット情報：
         *                                  文字列'##DUMMY_ALL##'が指定された場合は全てのoptionタグにselect属性を付加する(HtmlGrid等で使用)
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function __construct($elementID, $datasource, $selectedItems){
            parent::__construct($elementID, 'select');
            
            //optionタグ生成
            $selectedList   = (is_array($selectedItems) ? $selectedItems : array($selectedItems));
            $this->_options = array();
            $index          = 0;
            foreach ($datasource as $_value => $_caption){
                $option     = new HtmlElement($elementID.'_'.$index, 'option', array($_caption, 'value' => $_value));
                if (in_array($_value, $selectedList) || $selectedItems === '##DUMMY_ALL##'){
                    $option->attribute('selected');
                }
                $this->_options[]  = $option;
                ++$index;
            }
        }

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * エレメント組込処理
         * @param object    $parent         親オブジェクト(Region)
         * @param string    $containerID    組込先エレメントID(NULLの場合はbodyタグ)
         */
        //-------------------------------------------------------------------------------------------------------------------
        protected function mount($parent, $containerID = NULL){
            parent::mount($parent, $containerID);

            //optionタグ追加
            foreach ($this->_options as $_option){
                $parent->appendElement($_option, $this->_elementID);
            }
        }
    }
    
    //========================================================================================================================
    /**
     * コンボボックス
     */
    //========================================================================================================================
    class Combobox extends Select{
        public function __construct($elementID, $datasource, $selectedItems = array()){
            $select     = parent::__construct($elementID, $datasource, $selectedItems);
        }
    }
    
    //========================================================================================================================
    /**
     * リストボックス
     */
    //========================================================================================================================
    class Listbox extends Select{
        public function __construct($elementID, $datasource, $selectedItems = array()){
            $select     = parent::__construct($elementID, $datasource, $selectedItems);
            $this->attribute('multiple');
        }
    }
    
    //========================================================================================================================
    /**
     * テーブルクラス
     */
    //========================================================================================================================
    class Table extends Components{
        private $_datasource;
        private $_width;            //全体サイズ幅
        private $_height;           //全体サイズ高
        private $_coumuns;          //カラム情報
        private $_headerSW;         //ヘッダ表示用非切替
        private $_tableAttr;        //tableタグ属性リスト
        private $_headCellAttr;     //theadタグ属性リスト
        private $_gridCellAttr;     //tbodyタグ属性リスト
        private $_config;           //各種設定
        private $_startRange;       //対象カラム開始インデックス
        private $_endRange;         //対象カラム終端インデックス
    
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * コンストラクタ
         * @param object    $elementID      エレメントID
         * @param array     $datasource     データーソース：連想配列（フィールド名($columns内の'dataIndex'で対応づける)
         * @param array     $config         表示フォーマット情報
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function __construct($elementID, $datasource, $config){
            parent::__construct($elementID, 'table');
            
            $this->_datasource  = $datasource;
            $this->_headerSW    = TRUE;
            $this->_width       = $config['width'];
            $this->_height      = $config['height'];
            $this->_columns     = $config['columns'];
            $this->_startRange  = 0;
            $this->_endRange    = count($config['columns']) - 1;

            //---------------------------------------------------------------------------------------------------------------
            //tableタグ属性デフォルト値
            $this->_tableAttr  = array(
                'frame'             => 'box',
                'border'            => 1,
                'bordercolor'       => 'silver',
                'rules'             => 'all',
                'cellpadding'       => 0,
                'cellspacing'       => 0,
            );
            
            //header部属性デフォルト値
            $this->_headCellAttr  = array(
                'align'             => 'center',
                'bgcolor'           => 'gainsboro',
            );
            
            //grid部属性デフォルト値
            $this->_gridCellAttr    = array(
            );

            //---------------------------------------------------------------------------------------------------------------
            //各種設定
            $this->_config  = array(
                'cellHeight'    => 24,
                'zebraColors'   => array('white', 'whitesmoke'),
            );
        }

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * エレメント組込処理
         * @param object    $parent         親オブジェクト(Region)
         * @param string    $containerID    組込先エレメントID(NULLの場合はbodyタグ)
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function mount($parent, $containerID){
            parent::mount($parent, $containerID);

            //tableタグ生成
            $this->attribute($this->_tableAttr);

            //ヘッダ行タグ生成
            if ($this->_headerSW){
                $this->mountHeader($parent, $this->_elementID);
            }

            //データ部生成
            $tbodyID    = $this->_elementID.'_TBODY';
            $tbody      = new HtmlElement($tbodyID, 'tbody');
            $parent->appendElement($tbody, $this->_elementID);
            
            foreach ($this->_datasource as $_index => $_rec){
                //trタグ生成
                $rowID  = $this->_elementID.'_ROW_'.$_index;
                $row    = new HtmlElement($rowID, 'tr');
                $row->style('height', $this->_config['cellHeight'].'px');
                $parent->appendElement($row, $tbodyID);
                $colorCount     = count($this->_config['zebraColors']);
                if ($colorCount > 1){
                    $row->attribute('bgcolor', $this->_config['zebraColors'][$_index % $colorCount]);
                }

                //tdタグ生成
                $columns    = $this->_columns;
                foreach ($columns as $_colIndex => $_column){
                    //対象カラムチェック
                    if (($_colIndex < $this->_startRange) || ($_colIndex > $this->_endRange)){
                        continue;
                    }
                
                    //セル表示
                    if (array_key_exists($_column['dataIndex'], $_rec)){
                        //tdタグ編集
                        $cell   = new HtmlElement($this->_elementID.'_'.$_column['dataIndex'].'_'.$_index, 'td');
                        if ($_index == 0){
                            $cell->attribute('width', $_column['width']);
                        }
                        $cellAttr   = (array_key_exists('attribute', $_column) ? (is_array($_column['attribute']) ? $_column['attribute'] : array()) : array());
                        $cell->attribute(array_merge($cellAttr, $this->_gridCellAttr));
                        $parent->appendElement($cell, $rowID);

                        //表示データ編集
                        $cellElementID  = $this->_elementID.'_'.$_column['dataIndex'].'_CELL_'.$_index;
                        $tagName        = (array_key_exists('xtype', $this->_columns[$_colIndex]) ? $_column['xtype'] : 'TEXT_NODE');
                        $cellContent    = $this->_editTag($cellElementID, $tagName, $_column, $_rec, $cell);
                        $parent->appendElement($cellContent, $this->_elementID.'_'.$_column['dataIndex'].'_'.$_index);
                    }
                }
            }
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * タグ種類別編集処理
         * @param string    $elementID  生成エレメントID
         * @param string    $tagName    生成タグ名
         * @param array     $column     テーブルフォーマット情報の連想配列
         * @param array     $rec        データーソースレコードイメージの連想配列
         * @return object   エレメントオブジェクト
         */
        //-------------------------------------------------------------------------------------------------------------------
        private function _editTag($elementID, $tagName, $column, $rec, $cell){
            switch ($tagName){
                case 'input':
                    switch ($column['xconfig']['type']){
                        case 'button':
                            $cellContent    = new HtmlElement($elementID, $tagName, array_merge($column['xconfig'], array('value' => $rec[$column['dataIndex']])));
                            $cellContent->style(array('width' => $column['width'].'px', 'height' => ($this->_config['cellHeight'] - 2).'px'));
                            return $cellContent;
                            break;
                            
                        //チェックボックス：データソース[dataIndex]の値が、xconfig[value]の値と等しい場合にcheckedを付加
                        case 'checkbox':
                            $checked    = ($rec[$column['dataIndex']] === $column['xconfig']['value'] ? array('checked' => TRUE) : array());
                            $cellContent    = new HtmlElement($elementID, $tagName, array_merge($column['xconfig'], $checked));
                            $cell->attribute(array('align' => 'center'));
                            return $cellContent;
                            break;
                            
                        default:
                            return new HtmlElement($elementID, $tagName, array_merge($column['xconfig'], array('value' => $rec[$column['dataIndex']])));
                    }
                    break;
                    
                //リンク：データソース[dataIndex]の値を表示し、データソース[xconfig[dataIndex]]の値をリンク先(href)に設定
                case 'a':
                    $attrList       = array('TEXT_NODE' => $rec[$column['dataIndex']],
                                            'href'      => $rec[$column['xconfig']['dataIndex']]);
                    return new HtmlElement($elementID, $tagName, $attrList);
                    
                default:
                    return new HtmlElement($elementID, 'TEXT_NODE', $rec[$column['dataIndex']]);
                    break;
            }
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * ヘッダ部組込処理(tableタグ付き)
         * @param object    $parent         親オブジェクト(Region)
         * @param string    $containerID    組込先エレメントID(NULLの場合はbodyタグ)
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function mountHeaderWithTableTag($parent, $containerID){
            $tableID    = $containerID.'_TABLE';
            $headTable  = new HtmlElement($tableID, 'table');
            $headTable->attribute($this->_tableAttr);
            $parent->appendElement($headTable, $containerID);
            
            $this->mountHeader($parent, $tableID);
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * ヘッダ部組込処理
         * @param object    $parent         親オブジェクト(Region)
         * @param string    $containerID    組込先エレメントID(NULLの場合はbodyタグ)
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function mountHeader($parent, $containerID){
            $theadID    = $containerID.'_THEAD';
            $thead      = new HtmlElement($theadID, 'thead');
            $parent->appendElement($thead, $containerID);
            
            $rowID      = $containerID.'_HEADER';
            $row        = new HtmlElement($rowID, 'tr');
            $parent->appendElement($row, $theadID);

            $columns    = $this->_columns;
            foreach ($columns as $_colIndex => $_column){
                //対象カラムチェック
                if (($_colIndex < $this->_startRange) || ($_colIndex > $this->_endRange)){
                    continue;
                }
            
                //セル表示
                $cell   = new HtmlElement($containerID.'_'.$_column['dataIndex'], 'td', array($_column['header'], 'width' => $_column['width']));
                $cell->attribute($this->_headCellAttr);
                $parent->appendElement($cell, $rowID);
            }
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * ヘッダー非表示
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function headerOff(){
            $this->_headerSW    = FALSE;
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 対象カラム範囲指定
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function columnRange($startIndex, $endIndex){
            $this->_startRange  = $startIndex;
            $this->_endRange    = $endIndex;
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * tableタグ属性セット
         * @param array     $attribute  属性（属性名=>属性値の連想配列または属性名文字列
         * @param string    $value      属性値（$attributeが連想配列の場合は不要）
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function tableAttribute($attribute, $value = NULL){
            $attr   = (is_array($attribute) ? $attribute : array($attribute => $value));
            $this->_tableAttr  = array_merge($this->_tableAttr, $attr);
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * ヘッダ部属性セット
         * @param array     $attribute  属性（属性名=>属性値の連想配列または属性名文字列
         * @param string    $value      属性値（$attributeが連想配列の場合は不要）
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function headCellAttribute($attribute, $value = NULL){
            $attr   = (is_array($attribute) ? $attribute : array($attribute => $value));
            $this->_headCellAttr  = array_merge($this->_headCellAttr, $attr);
        }
        
        //-------------------------------------------------------------------------------------------------------------------
        /**
         * データ部属性セット
         * @param array     $attribute  属性（属性名=>属性値の連想配列または属性名文字列
         * @param string    $value      属性値（$attributeが連想配列の場合は不要）
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function gridCellAttribute($attribute, $value = NULL){
            $attr   = (is_array($attribute) ? $attribute : array($attribute => $value));
            $this->_gridCellAttr  = array_merge($this->_gridCellAttr, $attr);
        }

        //-------------------------------------------------------------------------------------------------------------------
        /**
         * 各種グリッド設定値セット
         * @param array     $config     設定（設定名=>各種設定値の連想配列 の連想配列)
         */
        //-------------------------------------------------------------------------------------------------------------------
        public function config($config, $value = NULL){
            $conf   = (is_array($config) ? $config : array($config => $value));
            $this->_config  = array_merge($this->_config, $conf);
        }
    }

?>
