summaryrefslogtreecommitdiff
path: root/lib/prado/framework/Web/UI/ActiveControls/TBaseActiveControl.php
blob: 01583eba10183e785a630ce4949b0a2c21135db0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
<?php
/**
 * TBaseActiveControl and TBaseActiveCallbackControl class file.
 *
 * @author Wei Zhuo <weizhuo[at]gamil[dot]com>
 * @link https://github.com/pradosoft/prado
 * @copyright Copyright &copy; 2005-2015 The PRADO Group
 * @license https://github.com/pradosoft/prado/blob/master/COPYRIGHT
 * @package System.Web.UI.ActiveControls
 */

Prado::using('System.Web.UI.ActiveControls.TCallbackClientSide');

/**
 * TBaseActiveControl class provided additional basic property for every
 * active control. An instance of TBaseActiveControl or its decendent
 * TBaseActiveCallbackControl is created by {@link TActiveControlAdapter::getBaseActiveControl()}
 * method.
 *
 * The {@link setEnableUpdate EnableUpdate} property determines wether the active
 * control is allowed to update the contents of the client-side when the callback
 * response returns.
 *
 * @author Wei Zhuo <weizhuo[at]gamil[dot]com>
 * @package System.Web.UI.ActiveControls
 * @since 3.1
 */
class TBaseActiveControl extends TComponent
{
	/**
	 * @var TMap map of active control options.
	 */
	private $_options;
	/**
	 * @var TControl attached control.
	 */
	private $_control;

	/**
	 * Constructor. Attach a base active control to an active control instance.
	 * @param TControl active control
	 */
	public function __construct($control)
	{
		$this->_control = $control;
		$this->_options = new TMap;
	}

	/**
	 * Sets a named options with a value. Options are used to store and retrive
	 * named values for the base active controls.
	 * @param string option name.
	 * @param mixed new value.
	 * @param mixed default value.
	 * @return mixed options value.
	 */
	protected function setOption($name,$value,$default=null)
	{
		$value = ($value===null) ? $default : $value;
		if($value!==null)
			$this->_options->add($name,$value);
	}

	/**
	 * Gets an option named value. Options are used to store and retrive
	 * named values for the base active controls.
	 * @param string option name.
	 * @param mixed default value.
	 * @return mixed options value.
	 */
	protected function getOption($name,$default=null)
	{
		$item = $this->_options->itemAt($name);
		return ($item===null) ? $default : $item;
	}

	/**
	 * @return TMap active control options
	 */
	protected function getOptions()
	{
		return $this->_options;
	}

	/**
	 * @return TPage the page containing the attached control.
	 */
	protected function getPage()
	{
		return $this->_control->getPage();
	}

	/**
	 * @return TControl the attached control.
	 */
	protected function getControl()
	{
		return $this->_control;
	}

	/**
	 * @param boolean true to allow fine grain callback updates.
	 */
	public function setEnableUpdate($value)
	{
		$this->setOption('EnableUpdate', TPropertyValue::ensureBoolean($value), true);
	}

	/**
	 * @return boolean true to allow fine grain callback updates.
	 */
	public function getEnableUpdate()
	{
		return $this->getOption('EnableUpdate', true);
	}

	/**
	 * Returns true if callback response is allowed to update the browser contents.
	 * Is is true if the control is initilized, and is a callback request and
	 * the {@link setEnableUpdate EnableUpdate} property is true and
	 * the page is not loading post data.
	 * @return boolean true if the callback response is allowed update
	 * client-side contents.
	 */
	public function canUpdateClientSide($bDontRequireVisibility=false)
	{
		return 	$this->getControl()->getHasChildInitialized()
				&& $this->getPage()->getIsLoadingPostData() == false
				&& $this->getPage()->getIsCallback()
				&& $this->getEnableUpdate()
				&& ($bDontRequireVisibility || $this->getControl()->getVisible());
	}
}

/**
 * TBaseActiveCallbackControl is a common set of options and functionality for
 * active controls that can perform callback requests.
 *
 * The properties of TBaseActiveCallbackControl can be accessed and changed from
 * each individual active controls' {@link getActiveControl ActiveControl}
 * property.
 *
 * The following example sets the validation group property of a TCallback component.
 * <code>
 * 	<com:TCallback ActiveControl.ValidationGroup="group1" ... />
 * </code>
 *
 * Additional client-side options and events can be set using the
 * {@link getClientSide ClientSide} property. The following example shows
 * an alert box when a TCallback component response returns successfully.
 * <code>
 * 	<com:TCallback ActiveControl.ClientSide.OnSuccess="alert('ok!')" ... />
 * </code>
 *
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 * @package System.Web.UI.ActiveControls
 * @since 3.1
 */
class TBaseActiveCallbackControl extends TBaseActiveControl
{
	/**
	 * Callback client-side options can be set by setting the properties of
	 * the ClientSide property. E.g. <com:TCallback ActiveControl.ClientSide.OnSuccess="..." />
	 * See {@link TCallbackClientSide} for details on the properties of ClientSide.
	 * @return TCallbackClientSide client-side callback options.
	 */
	public function getClientSide()
	{
		if(($client = $this->getOption('ClientSide'))===null)
		{
			$client = $this->createClientSide();
			$this->setOption('ClientSide', $client);
		}
		return $client;
	}

	/**
	 * Sets the client side options. Can only be set when client side is null.
	 * @param TCallbackClientSide client side options.
	 */
	public function setClientSide($client)
	{
		if( $this->getOption('ClientSide')===null)
			$this->setOption('ClientSide', $client);
		else
			throw new TConfigurationException(
				'active_controls_client_side_exists', $this->getControl()->getID());
	}

	/**
	 * @return TCallbackClientSide callback client-side options.
	 */
	protected function createClientSide()
	{
		return new TCallbackClientSide;
	}

	/**
	 * Sets default callback options. Takes the ID of a TCallbackOptions
	 * component to duplicate the client-side
	 * options for this control. The {@link getClientSide ClientSide}
	 * subproperties takes precedence over the CallbackOptions property.
	 * @param string ID of a TCallbackOptions control from which ClientSide
	 * options are cloned.
	 */
	public function setCallbackOptions($value)
	{
		$this->setOption('CallbackOptions', $value, '');
	}

	/**
	 * @return string ID of a TCallbackOptions control from which ClientSide
	 * options are duplicated.
	 */
	public function getCallbackOptions()
	{
		return $this->getOption('CallbackOptions', '');
	}

	/**
	 * Returns an array of default callback client-side options. The default options
	 * are obtained from the client-side options of a TCallbackOptions control with
	 * ID specified by {@link setCallbackOptions CallbackOptions}.
	 * @return array list of default callback client-side options.
	 */
	protected function getDefaultClientSideOptions()
	{
		if(($id=$this->getCallbackOptions())!=='')
		{
			if(($pos=strrpos($id,'.'))!==false)
			{
				$control=$this->getControl()->getSubProperty(substr($id,0,$pos));
				$newid=substr($id,$pos+1);
				if ($control!==null)
					$control=$control->$newid;
			}
			else
			{
				// TCheckBoxList overrides findControl() with a fake implementation
				// but accepts a second parameter to use the standard one
				$control=$this->getControl()->findControl($id, true);
			}

			if($control instanceof TCallbackOptions)
				return $control->getClientSide()->getOptions()->toArray();
			else
				throw new TConfigurationException('callback_invalid_callback_options', $this->getControl()->getID(), $id);
		}

		return array();
	}

	/**
	 * @return boolean whether callback event trigger by this button will cause
	 * input validation, default is true
	 */
	public function getCausesValidation()
	{
		return $this->getOption('CausesValidation',true);
	}

	/**
	 * @param boolean whether callback event trigger by this button will cause
	 * input validation
	 */
	public function setCausesValidation($value)
	{
		$this->setOption('CausesValidation',TPropertyValue::ensureBoolean($value),true);
	}

	/**
	 * @return string the group of validators which the button causes validation
	 * upon callback
	 */
	public function getValidationGroup()
	{
		return $this->getOption('ValidationGroup','');
	}

	/**
	 * @param string the group of validators which the button causes validation
	 * upon callback
	 */
	public function setValidationGroup($value)
	{
		$this->setOption('ValidationGroup',$value,'');
	}

	/**
	 * @return boolean whether to perform validation if the callback is
	 * requested.
	 */
	public function canCauseValidation()
	{
		if($this->getCausesValidation())
		{
			$group=$this->getValidationGroup();
			return $this->getPage()->getValidators($group)->getCount()>0;
		}
		else
			return false;
	}

	/**
	 * @param mixed callback parameter value.
	 */
	public function setCallbackParameter($value)
	{
		$this->setOption('CallbackParameter', $value, '');
	}

	/**
	 * @return mixed callback parameter value.
	 */
	public function getCallbackParameter()
	{
		return $this->getOption('CallbackParameter', '');
	}


	/**
	 * @return array list of callback javascript options.
	 */
	protected function getClientSideOptions()
	{
		$default = $this->getDefaultClientSideOptions();
		$options = array_merge($default,$this->getClientSide()->getOptions()->toArray());
		$validate = $this->getCausesValidation();
		$options['CausesValidation']= $validate ? '' : false;
		$options['ValidationGroup']=$this->getValidationGroup();
		$options['CallbackParameter'] = $this->getCallbackParameter();
		// needed for TCallback
		if(!isset($options['EventTarget']))
			$options['EventTarget'] = $this->getControl()->getUniqueID();
		return $options;
	}

	/**
	 * Registers the callback control javascript code. Client-side options are
	 * merged and passed to the javascript code. This method should be called by
	 * Active component developers wanting to register the javascript to initialize
	 * the active component with additional options offered by the
	 * {@link getClientSide ClientSide} property.
	 * @param string client side javascript class name.
	 * @param array additional callback options.
	 */
	public function registerCallbackClientScript($class,$options=null)
	{
		$cs = $this->getPage()->getClientScript();
		if(is_array($options))
			$options = array_merge($this->getClientSideOptions(),$options);
		else
			$options = $this->getClientSideOptions();

		//remove true as default to save bytes
		if($options['CausesValidation']===true)
			$options['CausesValidation']='';
		$cs->registerCallbackControl($class, $options);
	}

	/**
	 * Returns the javascript callback request instance. To invoke a callback
	 * request for this control call the <tt>dispatch()</tt> method on the
	 * request instance. Example code in javascript
	 * <code>
	 *   var request = <%= $this->mycallback->ActiveControl->Javascript %>;
	 *   request.setParameter('hello');
	 *   request.dispatch(); //make the callback request.
	 * </code>
	 *
	 * Alternatively,
	 * <code>
	 * //dispatches immediately
	 * Prado.Callback("<%= $this->mycallback->UniqueID %>",
	 *    $this->mycallback->ActiveControl->JsCallbackOptions);
	 * </code>
	 * @return string javascript client-side callback request object (javascript
	 * code)
	 */
	public function getJavascript()
	{
		$client = $this->getPage()->getClientScript();
		return $client->getCallbackReference($this->getControl(),$this->getClientSideOptions());
	}

	/**
	 * @param string callback requestion options as javascript code.
	 */
	public function getJsCallbackOptions()
	{
		return TJavaScript::encode($this->getClientSideOptions());
	}
}