<?php
    //========================================================================================================================
    /**
     * MVCビュークラス：Ajaxビュー
     *
     * リクエスト変数($_REQUEST)のラッパークラス
     *
     * 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.'/View.php');

    class AjaxView extends View{
        protected $_app;                        //アプリケーションオブジェクト
        protected $_clientView = array();       //Ajax用クライアントビュー
        protected $_clientContainer = array();  //クライアントビュー用コンテナID
        
        //変数リスト
        private $_appendElementList = array(AJAX_ITEM_COUNT => '');
        private $_modifyStyleList = array(AJAX_ITEM_COUNT => '');
        private $_modifyAttrList = array(AJAX_ITEM_COUNT => '');
        private $_modifyHeadTag = array(AJAX_ITEM_COUNT => '');
        private $_responseList  = array(AJAX_ITEM_COUNT => '');

        /**
         * コンストラクタ/デストラクタ
         * @param object    $application    アプリケーションオブジェクト
         * @param object    $eventManager   イベントマネージャーオブジェクト：省略した場合は自動生成
         */
        public function __construct($application, $eventManager = NULL){
            parent::__construct($application, $eventManager);
            $this->_className   = 'AjaxView';
        }

        /**
         * レスポンス文字列生成
         * @param boolean   $output     出力要否：trueを指定した場合はレスポンスを出力する
         * @return string   レスポンスJSON文字列(引数$outputにTRUEを指定した場合は戻り値なしで直接出力する)
         */
        public function ajaxResponse($output = TRUE){
            //クライアントビュー処理
            foreach ($this->_clientView as $_idx => $_clientView){
                $this->addAjaxResponse($this->_clientContainer[$_idx], $_clientView->response(FALSE));
                $this->addModifyHeadTag($this->_clientContainer[$_idx], $_clientView->responseHeadItems());
                $this->addClientProc($_clientView->clientProc());
            }

            //レスポンスアイテム件数セット
            $this->_appendElementList[AJAX_ITEM_COUNT] = count($this->_appendElementList) - 1;
            $this->_modifyStyleList[AJAX_ITEM_COUNT]   = count($this->_modifyStyleList) - 1;
            $this->_modifyAttrList[AJAX_ITEM_COUNT]    = count($this->_modifyAttrList) - 1;
            $this->_clientProcList[AJAX_ITEM_COUNT]    = count($this->_clientProcList);
            $this->_modifyHeadTag[AJAX_ITEM_COUNT]     = count($this->_modifyHeadTag) - 1;
            $this->_responseList[AJAX_ITEM_COUNT]      = count($this->_responseList) - 1;

            //レスポンスリスト作成
            $wResponse  = array();
            $wResponse['LB_elements']       = $this->_appendElementList;
            $wResponse['LB_style']          = $this->_modifyStyleList;
            $wResponse['LB_attribute']      = $this->_modifyAttrList;
            $wResponse['LB_clientProc']     = $this->_clientProcList;
            $wResponse['LB_modifyHeadTag']  = $this->_modifyHeadTag;
            $wResponse['LB_contents']       = $this->_responseList;

            //レスポンス作成
            if ($output === TRUE){
                print(json_encode($wResponse));
            }
            else{
                return(json_encode($wResponse));
            }
        }

        /*
         * クライアントビュー追加
         * @param object $clientProc    生成済みクライアントビューオブジェクト
         * @param object $contianer     置換先コンテナID 
         */
        public function addClientView($clientView, $contianer){
            $this->_clientView[]        = $clientView;
            $this->_clientContainer[]   = $contianer;
        }

        /*
         * Embededビュー追加
         * @param object $clientProc    生成済みクライアントビューオブジェクト
         * @param object $contianer     置換先コンテナID 
         */
        public function addEmbededView($embededView, $contianer){
            $this->addClientView($embededView, $contianer);
        }

        /**
         * レスポンスメンバー追加
         * @param string    $key        識別インデックス(エレメントIDの場合はクライアント側で値をエレメントにセットする)
         * @param string    $response   レスポンス文字列
         */
        public function addAjaxResponse($key, $response){
            $this->_responseList[$key]  = $response;
        }

        //-- セレクトタグ用
        public function addAjaxReplaceSelect($key, $options, $selected = array()){
            $this->addAjaxResponse($key, array('##LABBITBOX##', 'replaceSelect', array('options' => $options, 'selected' => $selected)));
        }

        /**
         * Ajaxエレメント追加
         * @param string        $elementID      更新対象のエレメントID
         * @param string        $tagName        タグ名
         * @param string        $value          属性値(任意)
         * @param string        $contianer      親エレメントID
         */
        public function appendElement($elementID, $tagName, $value = '', $container = 'body'){
            $this->_appendElementList[$elementID]    = array($tagName, $value, $container);
        }

        /**
         * Ajaxスタイル更新
         * 指定したエレメントのスタイルや属性をクライアントサイドで更新
         * @param string        $elementID      更新対象のエレメントID
         * @param string        $name           スタイル名
         * @param string        $value          スタイル値
         */
        public function addModifyStyle($elementID, $name, $value = NULL){
            $wStyle     = (is_array($name) ? $name : array($name => $value));
            foreach($wStyle as $_name => $_value){
                $wWord  = str_replace(' ','',ucwords(str_replace('-',' ',$_name)));   
                $wWord[0] = strtolower($wWord[0]);  
                $wJsStyle[$wWord] = $_value;   
            }
            if (!array_key_exists($elementID, $this->_modifyStyleList)){
                $this->_modifyStyleList[$elementID]     = array();
            }
            $this->_modifyStyleList[$elementID]   = array_merge($this->_modifyStyleList[$elementID], $wJsStyle);
        }

        /**
         * Ajax属性更新
         * 指定したエレメントの属性や属性をクライアントサイドで更新
         * @param string        $elementID      更新対象のエレメントID
         * @param string        $name           属性名
         * @param string        $value          属性値
         */
        public function addModifyAttr($elementID, $name, $value = NULL){
            $wAttr      = (is_array($name) ? $name : array($name => $value));
            if (!array_key_exists($elementID, $this->_modifyAttrList)){
                $this->_modifyAttrList[$elementID]     = array();
            }
            $this->_modifyAttrList[$elementID]    = array_merge($this->_modifyAttrList[$elementID], $wAttr);
        }

        public function addModifyHeadTag($containerID, $modifyHeadTag, $mode = 'REPLACE'){
            $wConfig    = array();
            $wConfig['LB_ID']   = $containerID;
            $wConfig['MODE']    = $mode;

            $this->_modifyHeadTag['CONFIG'] = $wConfig;
            $this->_modifyHeadTag['DATA']   = $modifyHeadTag;
        }

        /**
         * クライアント側処理追加
         */
        public function addClientProc($clientProc){
            $wClientProc    = (is_array($clientProc) ? $clientProc : array($clientProc));
            $this->_clientProcList     = array_merge($this->_clientProcList, $wClientProc);
        }

        /**
         * リダイレクト処理
         * @param string    $url    リダイレクト先のURL
         */
        public function redirect($url = '', $action = '', $method = '', $type = '', $params = array()){
            $this->appendElement('LB___redirect', 'form');
            $this->addModifyAttr('LB___redirect', 'action', $url);
            $this->addModifyAttr('LB___redirect', 'method', 'post');
            $this->addClientProc("$('LB___redirect').submit();");

            if ($action !== ''){
                $this->appendElement('action', 'input', $action, 'LB___redirect');
                $this->addModifyAttr('action', 'type', 'hidden');
            }
            if ($method !== ''){
                $this->appendElement('method', 'input', $method, 'LB___redirect');
                $this->addModifyAttr('method', 'type', 'hidden');
            }
            if ($type !== ''){
                $this->appendElement('type', 'input', $type, 'LB___redirect');
                $this->addModifyAttr('type', 'type', 'hidden');
            }
            
            foreach ($params as $_key => $_value){
                $this->appendElement($_key, 'input', $_value, 'LB___redirect');
                $this->addModifyAttr($_key, 'type', 'hidden');
            }
        }
    }
?>
