* @link http://www.pradosoft.com/ * @copyright Copyright © 2005-2014 PradoSoft * @license http://www.pradosoft.com/license/ * @package Prado\Web\UI\ActiveControls */ namespace Prado\Web\UI\ActiveControls; /** * TCallbackClientScript class. * * The TCallbackClientScript class provides corresponding methods that can be * executed on the client-side (i.e. the browser client that is viewing * the page) during a callback response. * * The available methods includes setting/clicking input elements, changing Css * styles, hiding/showing elements, and adding visual effects to elements on the * page. The client-side methods can be access through the CallbackClient * property available in TPage. * * For example, to hide "$myTextBox" element during callback response, do * * $this->getPage()->getCallbackClient()->hide($myTextBox); * * * To call a specific jQuery method on an element, use the {@link jQuery} method: * * // simple example: focus a textbox * $this->getCallbackClient()->jQuery($myTextBox, 'focus'); * * // complex example: resize a textbox using an animation * $this->getCallbackClient()->jQuery($myTextBox, 'animate', array( * array( 'width' => '+=100', * 'height' => '+=50' * ), * array('duration' => 1000) * )); * * * To call a jQueryUI effect on an element, use the {@link juiEffect} method: * * // simple example: focus a textbox * $this->getCallbackClient()->juiEffect($myTextBox, 'highlight'); * * * In order to use the jQueryUI effects, the jqueryui script must be registered: * * $this->getPage()->getClientScript()->registerPradoScript('jqueryui'); * * * @author Wei Zhuo * @author Fabio Bas * @package Prado\Web\UI\ActiveControls * @since 3.1 */ class TCallbackClientScript extends TApplicationComponent { /** * @var TList list of client functions to execute. */ private $_actions; /** * Constructor. */ public function __construct() { $this->_actions = new TList; } /** * @return array list of client function to be executed during callback * response. */ public function getClientFunctionsToExecute() { return $this->_actions->toArray(); } /** * Executes a client-side statement. * @param string javascript function name * @param array list of arguments for the function */ public function callClientFunction($function, $params=array()) { if(!is_array($params)) $params = array($params); if(count($params) > 0) { if ($params[0] instanceof ISurroundable) $params[0] = $params[0]->getSurroundingTagID(); elseif($params[0] instanceof TControl) $params[0] = $params[0]->getClientID(); } $this->_actions->add(array($function => $params)); } /** * Executes a jQuery client-side method over an element. * @param string control or element id * @param string jQuery method name * @param array list of arguments for the function */ public function jQuery($element, $method, $params=array()) { if ($element instanceof ISurroundable) $element = $element->getSurroundingTagID(); elseif($element instanceof TControl) $element = $element->getClientID(); if(!is_array($params)) $params = array($params); $this->_actions->add(array('Prado.Element.j' => array($element, $method, $params))); } /** * Client script to set the value of a particular input element. * @param TControl control element to set the new value * @param string new value */ public function setValue($input, $text) { $this->jQuery($input, 'val', $text); } /** * Client script to select/clear/check a drop down list, check box list, * or radio button list. * The second parameter determines the selection method. Valid methods are * - Value, select or check by value * - Values, select or check by a list of values * - Index, select or check by index (zero based index) * - Indices, select or check by a list of index (zero based index) * - Clear, clears or selections or checks in the list * - All, select all * - Invert, invert the selection. * @param TControl list control * @param string selection method * @param string|int the value or index to select/check. * @param string selection control type, either 'check' or 'select' */ public function select($control, $method='Value', $value=null, $type=null) { $method = TPropertyValue::ensureEnum($method, 'Value', 'Index', 'Clear', 'Indices', 'Values', 'All', 'Invert'); $type = ($type===null) ? $this->getSelectionControlType($control) : $type; $total = $this->getSelectionControlIsListType($control) ? $control->getItemCount() : 1; // pass the ID to avoid getting the surrounding elements (ISurroundable) if($control instanceof TControl) $control = $control->getClientID(); $this->callClientFunction('Prado.Element.select', array($control, $type.$method, $value, $total)); } private function getSelectionControlType($control) { if(is_string($control)) return 'check'; if($control instanceof TCheckBoxList) return 'check'; if($control instanceof TCheckBox) return 'check'; return 'select'; } private function getSelectionControlIsListType($control) { return $control instanceof TListControl; } /** * Client script to click on an element. This client-side function is unpredictable. * * @param TControl control element or element id */ public function click($control) { $this->jQuery($control, 'trigger', 'click'); } /** * Client script to check or uncheck a checkbox or radio button. * @param TControl control element or element id * @param boolean check or uncheck the checkbox or radio button. */ public function check($checkbox, $checked=true) { $this->select($checkbox, "Value", $checked); } /** * Raise the client side event (given by $eventName) on a particular element. * @param TControl control element or element id * @param string Event name, e.g. "click" */ public function raiseClientEvent($control, $eventName) { $this->jQuery($control, 'trigger', $eventName); } /** * Sets the attribute of a particular control. * @param TControl control element or element id * @param string attribute name * @param string attribute value */ public function setAttribute($control, $name, $value) { // Attributes should be applied on Surrounding tag, except for 'disabled' attribute if ($control instanceof ISurroundable && strtolower($name)!=='disabled') $control=$control->getSurroundingTagID(); $this->callClientFunction('Prado.Element.setAttribute',array($control, $name, $value)); } /** * Sets the options of a select input element. * @param TControl control element or element id * @param TCollection a list of new options */ public function setListItems($control, $items) { $options = array(); if($control instanceof TListControl) { $promptText = $control->getPromptText(); $promptValue = $control->getPromptValue(); if($promptValue==='') $promptValue = $promptText; if($promptValue!=='') $options[] = array($promptText, $promptValue); } foreach($items as $item) { if($item->getHasAttributes()) $options[] = array($item->getText(),$item->getValue(), $item->getAttributes()->itemAt('Group')); else $options[] = array($item->getText(),$item->getValue()); } $this->callClientFunction('Prado.Element.setOptions', array($control, $options)); } /** * Shows an element by changing its CSS display style as empty. * @param TControl control element or element id */ public function show($element) { $this->jQuery($element, 'show'); } /** * Hides an element by changing its CSS display style to "none". * @param TControl control element or element id */ public function hide($element) { $this->jQuery($element, 'hide'); } /** * Toggles the visibility of the element. * @param TControl control element or element id * @param string visual effect, such as, 'fade' or 'slide'. * @param array additional options. */ public function toggle($element, $effect=null, $options=array()) { switch(strtolower($effect)) { case 'fade': $method='fadeToggle'; break; case 'slide': $method='slideToggle'; break; default: $method='toggle'; // avoid fancy effect by default if(!array_key_exists('duration', $options)) $options['duration']=0; break; } $this->jQuery($element, $method, $options); } /** * Removes an element from the HTML page. * @param TControl control element or element id */ public function remove($element) { $this->jQuery($element, 'remove'); } /** * Update the element's innerHTML with new content. * @param TControl control element or element id * @param TControl new HTML content, if content is of a TControl, the * controls render method is called. */ public function update($element, $content) { $this->jQuery($element, 'html', $content); } /** * Add a Css class name to the element. * @param TControl control element or element id * @param string CssClass name to add. */ public function addCssClass($element, $cssClass) { $this->jQuery($element, 'addClass', $cssClass); } /** * Remove a Css class name from the element. * @param TControl control element or element id * @param string CssClass name to remove. */ public function removeCssClass($element, $cssClass) { $this->jQuery($element, 'removeClass', $cssClass); } /** * Scroll the top of the browser viewing area to the location of the * element. * * @param TControl control element or element id * @param array additional options: 'duration' in ms, 'offset' from the top in pixels */ public function scrollTo($element, $options=array()) { $this->callClientFunction('Prado.Element.scrollTo', array($element, $options)); } /** * Focus on a particular element. * @param TControl control element or element id. */ public function focus($element) { $this->jQuery($element, 'trigger', 'focus'); } /** * Sets the style of element. The style must be a key-value array where the * key is the style property and the value is the style value. * @param TControl control element or element id * @param array list of key-value pairs as style property and style value. */ public function setStyle($element, $styles) { $this->jQuery($element, 'css', array($styles)); } /** * Append a HTML fragement to the element. * @param TControl control element or element id * @param string HTML fragement or the control to be rendered */ public function appendContent($element, $content) { $this->jQuery($element, 'append', $content); } /** * Prepend a HTML fragement to the element. * @param TControl control element or element id * @param string HTML fragement or the control to be rendered */ public function prependContent($element, $content) { $this->jQuery($element, 'prepend', $content); } /** * Insert a HTML fragement after the element. * @param TControl control element or element id * @param string HTML fragement or the control to be rendered */ public function insertContentAfter($element, $content) { $this->jQuery($element, 'after', $content); } /** * Insert a HTML fragement in before the element. * @param TControl control element or element id * @param string HTML fragement or the control to be rendered */ public function insertContentBefore($element, $content) { $this->jQuery($element, 'before', $content); } /** * Replace the content of an element with new content. The new content can * be a string or a TControl component. If the content parameter is * a TControl component, its rendered method will be called and its contents * will be used for replacement. * @param TControl control element or HTML element id. * @param string HTML fragement or the control to be rendered * @param string provide a custom boundary. * @see insertAbout * @see insertBelow * @see insertBefore * @see insertAfter */ protected function replace($element, $content, $boundary=null) { if($content instanceof TControl) { $boundary = $this->getRenderedContentBoundary($content); $content = null; } else if($content instanceof THtmlWriter) { $boundary = $this->getResponseContentBoundary($content); $content = null; } $this->callClientFunction('Prado.Element.replace', array($element, $content, $boundary)); } /** * Replace the content of an element with new content contained in writer. * @param TControl control element or HTML element id. * @param string HTML fragement or the control to be rendered */ public function replaceContent($element,$content) { $this->replace($element, $content); } /** * Evaluate a block of javascript enclosed in a boundary. * @param THtmlWriter writer for the content. */ public function evaluateScript($writer) { if($writer instanceof THtmlWriter) { $boundary = $this->getResponseContentBoundary($writer); $content = null; } else { $boundary = null; $content = $writer; } $this->callClientFunction('Prado.Element.evaluateScript', array($content, $boundary)); } /** * Appends a block of inline javascript enclosed in a boundary. * Similar to to evaluateScript(), but functions declared in the * inline block will be available to page elements. * @param THtmlWriter writer for the content. */ public function appendScriptBlock($content) { if($content instanceof TControl) { $boundary = $this->getRenderedContentBoundary($content); } elseif($content instanceof THtmlWriter) { $boundary = $this->getResponseContentBoundary($content); } $this->callClientFunction('Prado.Element.appendScriptBlock', array($boundary)); } /** * Renders the control and return the content boundary from * TCallbackResponseWriter. This method should only be used by framework * component developers. The render() method is defered to be called in the * TActivePageAdapter class. * @param TControl control to be rendered on callback response. * @return string the boundary for which the rendered content is wrapped. */ private function getRenderedContentBoundary($control) { $writer = $this->getResponse()->createHtmlWriter(); $adapter = $control->getPage()->getAdapter(); $adapter->registerControlToRender($control, $writer); return $writer->getWriter()->getBoundary(); } /** * @param THtmlWriter the writer responsible for rendering html content. * @return string content boundary. */ private function getResponseContentBoundary($html) { if($html instanceof THtmlWriter) { if($html->getWriter() instanceof TCallbackResponseWriter) return $html->getWriter()->getBoundary(); } return null; } /* VISUAL EFFECTS */ /** * Add a visual effect the element. * @param string visual effect function name. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function visualEffect($type, $element, $options=array()) { $this->jQuery($element, $type, $options); } /* BASIC EFFECTS (JQUERY CORE) */ /** * Visual Effect: Gradually make the element appear. * This effect doesn't need jQueryUI. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function fadeIn($element, $options=array()) { $this->visualEffect('fadeIn', $element, $options); } /** * Visual Effect: Gradually fade the element. * This effect doesn't need jQueryUI. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function fadeOut($element, $options=array()) { $this->visualEffect('fadeOut', $element, $options); } /** * Set the opacity on a html element or control. * This effect doesn't need jQueryUI. * @param TControl control element or element id * @param float opacity value between 1 and 0 */ public function fadeTo($element, $value, $duration=500) { $value = TPropertyValue::ensureFloat($value); $this->visualEffect('fadeTo', $element, array($duration, $value)); } /** * Visual Effect: Slide down. * This effect doesn't need jQueryUI. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function slideDown($element, $options=array()) { $this->visualEffect('slideDown', $element, $options); } /** * Visual Effect: Slide up. * This effect doesn't need jQueryUI. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function slideUp($element, $options=array()) { $this->visualEffect('slideUp', $element, $options); } /* OLD METHODS, DEPRECATED, BACKWARDS-COMPATIBILITY */ /** * Alias of fadeIn() * @deprecated since 3.4 * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function appear($element, $options=array()) { $this->fadeIn($element, $options); } /** * Alias of fadeOut() * @deprecated since 3.4 * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function fade($element, $options=array()) { $this->fadeOut($element, $options); } /** * Alias of fadeTo() * @deprecated since 3.4 * @param TControl control element or element id * @param float opacity value between 1 and 0 */ public function setOpacity($element, $value) { $this->fadeTo($element, $value); } /* JQUERY UI EFFECTS */ /** * Add a jQuery-ui effect the element. * This method needs jQueryUI. * @param string visual effect function name. * @param TControl control element or element id * @param array effect options. */ public function juiEffect($element, $effect, $options=array()) { $options['effect']=$effect; $this->jQuery($element, 'effect', array($options)); } /** * Visual Effect: Blind. * This effect needs jQueryUI. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function blind($element, $options=array()) { $this->juiEffect($element, 'blind', $options); } /** * Visual Effect: Drop out. * This effect needs jQueryUI. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function drop($element, $options=array()) { $this->juiEffect($element, 'drop', $options); } /** * Visual Effect: Fold. * This effect needs jQueryUI. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function fold($element, $options=array()) { $this->juiEffect($element, 'fold', $options); } /** * Visual Effect: Gradually make an element grow to a predetermined size. * This effect needs jQueryUI. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function size($element, $options=array()) { $this->juiEffect($element, 'size', $options); } /** * Visual Effect: Gradually grow and fade the element. * This effect needs jQueryUI. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function puff($element, $options=array()) { $this->juiEffect($element, 'puff', $options); } /** * Visual Effect: Pulsate. * This effect needs jQueryUI. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function pulsate($element, $options=array()) { $this->juiEffect($element, 'pulsate', $options); } /** * Visual Effect: Shake the element. * This effect needs jQueryUI. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function shake($element, $options=array()) { $this->juiEffect($element, 'shake', $options); } /** * Visual Effect: Scale the element. * This effect needs jQueryUI. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function scale($element, $options=array()) { $this->juiEffect($element, 'scale', $options); } /** * Visual Effect: High light the element for about 2 seconds. * This effect needs jQueryUI. * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function highlight($element, $options=array()) { $this->juiEffect($element, 'highlight', $options); } /* jui - OLD METHODS, DEPRECATED, BACKWARDS-COMPATIBILITY */ /** * Alias of blind(), presets the direction to 'down' * @deprecated since 3.4 * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function blindDown($element, $options=array()) { $options['direction']='down'; $this->blind($element, $options); } /** * Alias of blind(), presets the direction to 'up' * @deprecated since 3.4 * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function blindUp($element, $options=array()) { $options['direction']='up'; $this->blind($element, $options); } /** * Alias of drop() * @deprecated since 3.4 * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function dropOut($element, $options=array()) { $this->drop($element, $options); } /** * Alias of size() * @deprecated since 3.4 * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function grow($element, $options=array()) { $this->size($element, $options); } /** * Alias of scale() * @deprecated since 3.4 * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function shrink($element, $options=array()) { $options['percent']=0; $this->scale($element, $options); } /** * Alias of scale() * @deprecated since 3.4 * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function squish($element, $options=array()) { $options['origin']=array('top', 'left'); $options['percent']=0; $this->scale($element, $options); } /** * Alias of scale() * @deprecated since 3.4 * @param TControl control element or element id * @param array visual effect key-value pair options. */ public function switchOff($element, $options=array()) { $options['direction']='vertical'; $options['percent']=0; $this->scale($element, $options); } }