PageRenderTime 890ms CodeModel.GetById 403ms app.highlight 272ms RepoModel.GetById 140ms app.codeStats 1ms

/js/yii/base/CComponent.js

http://github.com/phpnode/YiiJS
JavaScript | 758 lines | 415 code | 15 blank | 328 comment | 141 complexity | 56a6792104a440b13d472142c521662f MD5 | raw file
  1/*global Yii, php, $, jQuery, alert, clearInterval, clearTimeout, document, event, frames, history, Image, location, name, navigator, Option, parent, screen, setInterval, setTimeout, window, XMLHttpRequest */
  2/**
  3 * CComponent is the base class for all components.
  4 * 
  5 * CComponent implements the protocol of defining, using properties and events.
  6 * 
  7 * A property is defined by a getter method, and/or a setter method.
  8 * Properties can be accessed in the way like accessing normal object members.
  9 * Reading or writing a property will cause the invocation of the corresponding
 10 * getter or setter method, e.g
 11 * <pre>
 12 * a=component.text;     // equivalent to $a=$component->getText();
 13 * component.text='abc';  // equivalent to $component->setText('abc');
 14 * </pre>
 15 * The signatures of getter and setter methods are as follows,
 16 * <pre>
 17 * // getter, defines a readable property 'text'
 18 * public function getText() { +++ }
 19 * // setter, defines a writable property 'text' with $value to be set to the property
 20 * public function setText(value) { +++ }
 21 * </pre>
 22 * 
 23 * An event is defined by the presence of a method whose name starts with 'on'.
 24 * The event name is the method name. When an event is raised, functions
 25 * (called event handlers) attached to the event will be invoked automatically.
 26 * 
 27 * An event can be raised by calling {@link raiseEvent} method, upon which
 28 * the attached event handlers will be invoked automatically in the order they
 29 * are attached to the event. Event handlers must have the following signature,
 30 * <pre>
 31 * function eventHandler(event) { +++ }
 32 * </pre>
 33 * where $event includes parameters associated with the event.
 34 * 
 35 * To attach an event handler to an event, see {@link attachEventHandler}.
 36 * You can also use the following syntax:
 37 * <pre>
 38 * component.onClick=callback;    // or $component->onClick->add($callback);
 39 * </pre>
 40 * where $callback refers to a valid PHP callback. Below we show some callback examples:
 41 * <pre>
 42 * 'handleOnClick'                   // handleOnClick() is a global function
 43 * [object,'handleOnClick']    // using $object->handleOnClick()
 44 * ['Page','handleOnClick']     // using Page::handleOnClick()
 45 * </pre>
 46 * 
 47 * To raise an event, use {@link raiseEvent}. The on-method defining an event is
 48 * commonly written like the following:
 49 * <pre>
 50 * public function onClick(event)
 51 * {
 52 *     this.raiseEvent('onClick',event);
 53 * }
 54 * </pre>
 55 * where <code>$event</code> is an instance of {@link CEvent} or its child class.
 56 * One can then raise the event by calling the on-method instead of {@link raiseEvent} directly.
 57 * 
 58 * Both property names and event names are case-insensitive.
 59 * 
 60 * Starting from version 1.0.2, CComponent supports behaviors. A behavior is an
 61 * instance of {@link IBehavior} which is attached to a component. The methods of
 62 * the behavior can be invoked as if they belong to the component. Multiple behaviors
 63 * can be attached to the same component.
 64 * 
 65 * To attach a behavior to a component, call {@link attachBehavior}; and to detach the behavior
 66 * from the component, call {@link detachBehavior}.
 67 * 
 68 * A behavior can be temporarily enabled or disabled by calling {@link enableBehavior}
 69 * or {@link disableBehavior}, respectively. When disabled, the behavior methods cannot
 70 * be invoked via the component.
 71 * 
 72 * Starting from version 1.1.0, a behavior's properties (either its public member variables or
 73 * its properties defined via getters and/or setters) can be accessed through the component it
 74 * is attached to.
 75 * 
 76 * @originalAuthor Qiang Xue <qiang.xue@gmail.com>
 77 * @version $Id: CComponent.php 3066 2011-03-13 14:22:55Z qiang.xue $
 78 * @package system.base
 79 * @since 1.0
 80 * @author Charles Pick
 81 * @class
 82 */
 83Yii.CComponent = function CComponent() {
 84};
 85Yii.CComponent.prototype._e = null;
 86Yii.CComponent.prototype._m = null;
 87/**
 88 * Gets the class name for this item.
 89 * Since JavaScript doesn't really support this we 
 90 * abuse function declarations to implement it,
 91 * for example instead of:
 92 * <pre>
 93 * Yii.Blah = function() { ... }
 94 * </pre>
 95 * we use:
 96 * <pre>
 97 * Yii.Blah = function Blah() { ... }
 98 * </pre>
 99 * We can now retrieve the name of the class by inspecting the constructor.
100 */
101Yii.CComponent.prototype.getClassName = function() {
102	var matches, className;
103	
104	matches = /function(.*)\((.*)\)/.exec((this).constructor);
105	if (matches) {
106		return php.trim(matches[1]);
107	}
108};
109/**
110 * Returns a property value, an event handler list or a behavior based on its name.
111 * Do not call this method. This is a PHP magic method that we override
112 * to allow using the following syntax to read a property or obtain event handlers:
113 * <pre>
114 * value=component.propertyName;
115 * handlers=component.eventName;
116 * </pre>
117 * @param {String} name the property name or event name
118 * @returns {Mixed} the property value, event handlers attached to the event, or the named behavior (since version 1.0.2)
119 * @throws {Yii.CException} if the property or event is not defined
120 * @see __set
121 */
122Yii.CComponent.prototype.get = function (name) {
123		var getter, i, object, nameParts = [], limit;
124		
125		if (name.indexOf !== undefined && name.indexOf(".") !== -1) {
126			nameParts = name.split(".");
127			name = nameParts.shift();
128		}
129		if (this[name] !== undefined) {
130			object = this[name];
131			if (nameParts.length > 0) {
132				if (object instanceof Yii.CComponent) {
133					return object.get(nameParts.join("."));
134				}
135				limit = nameParts.length;
136				for (i = 0; i < limit; i++) {
137					name = nameParts.shift();
138					object = object[name];
139					if (nameParts.length === 0) {
140						return object;
141					}
142					
143					if (object instanceof Yii.CComponent) {
144						return object.get(nameParts.join("."));
145					}
146				}
147			}
148			return object;
149		}
150		getter='get'+php.ucfirst(name);
151		if(php.method_exists(this,getter)) {
152			object = this[getter]();
153			if (nameParts.length > 0) {
154				if (object instanceof Yii.CComponent) {
155					return object.get(nameParts.join("."));
156				}
157				limit = nameParts.length;
158				for (i = 0; i < limit; i++) {
159					name = nameParts.shift();
160					object = object[name];
161					if (nameParts.length === 0) {
162						return object;
163					}
164					
165					if (object instanceof Yii.CComponent) {
166						return object.get(nameParts.join("."));
167					}
168					
169				}
170			}
171			return object;
172		}
173		else if(php.strncasecmp(name,'on',2)===0 && php.method_exists(this,name)) {
174			// duplicating getEventHandlers() here for performance
175			name=name.toLowerCase();
176			if(this._e[name] === undefined) {
177				this._e[name]=new Yii.CList();
178			}
179			return this._e[name];
180		}
181		else if(this._m !== null && this._m[name] !== undefined) {
182			return this._m[name];
183		}
184		else if(this._m !== null) {
185			for (i in this._m) {
186				if (this._m.hasOwnProperty(i)) {
187					
188					object = this._m[i];
189					try {
190						if(object.getEnabled() && (php.property_exists(object,name) || object.canGetProperty(name))) {
191							if (nameParts.length > 0) {
192								return object.get(nameParts.join("."));
193							}
194							return object.get(name);
195						}
196					}
197					catch (e) {
198						console.log(e);
199					}
200				}
201			}
202		}
203		console.log(this.getClassName() + " : " + name);
204		throw new Yii.CException(Yii.t('yii','Property "{class}.{property}" is not defined.',
205			{'{class}':this.getClassName(), '{property}':name}));
206	};
207/**
208 * Sets value of a component property.
209 * Do not call this method. This is a PHP magic method that we override
210 * to allow using the following syntax to set a property or attach an event handler
211 * <pre>
212 * this.propertyName=value;
213 * this.eventName=callback;
214 * </pre>
215 * @param {String} name the property name or the event name
216 * @param {Mixed} value the property value or callback
217 * @throws {Yii.CException} if the property/event is not defined or the property is read only.
218 * @see __get
219 */
220Yii.CComponent.prototype.set = function (name, value) {
221		var setter, i, object, nameParts = [];
222		if (name.indexOf(".") !== -1) {
223			nameParts = name.split(".");
224			name = nameParts.pop();
225			return (this.get(nameParts.join("."))[name] = value);
226		}
227		if (this[name] !== undefined) {
228			return (this[name] = value);
229		}
230		
231		setter='set'+php.ucfirst(name);
232		if(php.method_exists(this,setter)) {
233			return this[setter](value);
234		}
235		else if(php.strncasecmp(name,'on',2)===0 && php.method_exists(this,name)) {
236			// duplicating getEventHandlers() here for performance
237			name=name.toLowerCase();
238			if(this._e[name] === undefined) {
239				this._e[name]=new Yii.CList();
240			}
241			return this._e[name].add(value);
242		}
243		else if(this._m !== null) {
244			for (i in this._m) {
245				if (this._m.hasOwnProperty(i)) {
246					
247					object = this._m[i];
248					
249					if(object.getEnabled() && (php.property_exists(object,name) || object.canSetProperty(name))) {
250						return (object.set(name,value));
251					}
252				}
253			}
254		}
255		if(php.method_exists(this,'get'+php.ucfirst(name))) {
256			throw new Yii.CException(Yii.t('yii','Property "{class}.{property}" is read only.',
257				{'{class}':this.getClassName(), '{property}':name}));
258		}
259		else {
260			throw new Yii.CException(Yii.t('yii','Property "{class}.{property}" is not defined.',
261				{'{class}':this.getClassName(), '{property}':name}));
262		}
263	};
264/**
265 * Checks if a property value is null.
266 * Do not call this method. This is a PHP magic method that we override
267 * to allow using isset() to detect if a component property is set or not.
268 * @param {String} name the property name or the event name
269 * @since 1.0.1
270 */
271Yii.CComponent.prototype.isset = function (name) {
272		var getter, i, object, nameParts = [], value;
273		if (name.indexOf(".") !== -1) {
274			nameParts = name.split(".");
275			name = nameParts.pop();
276			try {
277				value = this.get(nameParts.join("."))[name];
278				if (value !== undefined && value !== null) {
279					return true;
280				}
281				return false;
282			}
283			catch (e) {
284				return false;
285			}
286		}
287		if (this[name] !== undefined) {
288			return true;
289		}
290		getter='get'+php.ucfirst(name);
291		if(php.method_exists(this,getter)) {
292			return (this[getter]()!==null);
293		}
294		else if(php.strncasecmp(name,'on',2)===0 && php.method_exists(this,name))
295		{
296			name=name.toLowerCase();
297			return this._e !== null && this._e[name] !== undefined && this._e[name].getCount();
298		}
299		else if(this._m !== null) {
300			if(this._m[name] !== undefined) {
301				return true;
302			}
303			for (i in this._m) {
304				if (this._m.hasOwnProperty(i)) {
305					object = this._m[i];
306					if(object.getEnabled() && (php.property_exists(object,name) || object.canGetProperty(name))) {
307						return true;
308					}
309				}
310			}
311		}
312		return false;
313	};
314/**
315 * Sets a component property to be null.
316 * Do not call this method. This is a PHP magic method that we override
317 * to allow using unset() to set a component property to be null.
318 * @param {String} name the property name or the event name
319 * @throws {Yii.CException} if the property is read only.
320 * @since 1.0.1
321 */
322Yii.CComponent.prototype.unset = function (name) {
323		var setter, i, object, nameParts = [];
324		if (name.indexOf(".") !== -1) {
325			nameParts = name.split(".");
326			name = nameParts.pop();
327			object = this.get(nameParts.join("."))[name];
328			if (object.unset !== undefined) {
329				return object.unset(name);
330			} 
331			return (this.get(nameParts.join("."))[name] = null);
332		}
333		setter='set'+php.ucfirst(name);
334		if (this[name] !== undefined) {
335			this[name] = null; 
336			return;
337		}
338		else if(php.method_exists(this,setter)) {
339			this[setter](null);
340		}
341		else if(php.strncasecmp(name,'on',2)===0 && php.method_exists(this,name)) {
342			delete this._e[name.toLowerCase()];
343		}
344		else if(this._m !== null)
345		{
346			if(this._m[name] !== undefined) {
347				this.detachBehavior(name);
348			}
349			else
350			{
351				for (i in this._m) {
352					if (this._m.hasOwnProperty(i)) {
353						object = this._m[i];
354						if(object.getEnabled())	{
355							if(php.property_exists(object,name)) {
356								return (object[name]=null);
357							}
358							else if(object.canSetProperty(name)) {
359								return object[setter](null);
360							}
361						}
362					}
363				}
364			}
365		}
366		else if(php.method_exists(this,'get'+name)) {
367			throw new Yii.CException(Yii.t('yii','Property "{class}.{property}" is read only.',
368				{'{class}':this.getClassName(), '{property}':name}));
369		}
370	};
371/**
372 * Calls the named method which is not a class method.
373 * Do not call this method. This is a PHP magic method that we override
374 * to implement the behavior feature.
375 * @param {String} name the method name
376 * @param {Array} parameters method parameters
377 * @returns {Mixed} the method return value
378 * @since 1.0.2
379 */
380Yii.CComponent.prototype.call = function (name, parameters) {
381		var i, object;
382		if (this[name] !== undefined) {
383			return php.call_user_func_array([this,name],parameters);
384		}
385		else if(this._m!==null) {
386			for (i in this._m) {
387				if (this._m.hasOwnProperty(i)) {
388					object = this._m[i];
389					if(object.getEnabled() && php.method_exists(object,name)) {
390						return php.call_user_func_array([object,name],parameters);
391					}
392				}
393			}
394		}
395		
396		throw new Yii.CException(Yii.t('yii','{class} does not have a method named "{name}".',
397			{'{class}':this.getClassName(), '{name}':name}));
398	};
399/**
400 * Returns the named behavior object.
401 * The name 'asa' stands for 'as a'.
402 * @param {String} behavior the behavior name
403 * @returns {IBehavior} the behavior object, or null if the behavior does not exist
404 * @since 1.0.2
405 */
406Yii.CComponent.prototype.asa = function (behavior) {
407		return this._m !== null && this._m[behavior] !== undefined ? this._m[behavior] : null;
408	};
409/**
410 * Attaches a list of behaviors to the component.
411 * Each behavior is indexed by its name and should be an instance of
412 * {@link IBehavior}, a string specifying the behavior class, or an
413 * array of the following structure:
414 * <pre>
415 * {
416 *     'class':'path.to.BehaviorClass',
417 *     'property1':'value1',
418 *     'property2':'value2',
419 * }
420 * </pre>
421 * @param {Array} behaviors list of behaviors to be attached to the component
422 * @since 1.0.2
423 */
424Yii.CComponent.prototype.attachBehaviors = function (behaviors) {
425		var name, behavior;
426		for (name in behaviors) {
427			if (behaviors.hasOwnProperty(name)) {
428				behavior = behaviors[name];
429				this.attachBehavior(name,behavior);
430			}
431		}
432	};
433/**
434 * Detaches all behaviors from the component.
435 * @since 1.0.2
436 */
437Yii.CComponent.prototype.detachBehaviors = function () {
438		var name, behavior;
439		if(this._m!==null) {
440			for (name in this._m) {
441				if (this._m.hasOwnProperty(name)) {
442					behavior = this._m[name];
443					this.detachBehavior(name);
444				}
445			}
446			this._m=null;
447		}
448	};
449/**
450 * Attaches a behavior to this component.
451 * This method will create the behavior object based on the given
452 * configuration. After that, the behavior object will be initialized
453 * by calling its {@link IBehavior::attach} method.
454 * @param {String} name the behavior's name. It should uniquely identify this behavior.
455 * @param {Mixed} behavior the behavior configuration. This is passed as the first
456 * parameter to {@link YiiBase::createComponent} to create the behavior object.
457 * @returns {IBehavior} the behavior object
458 * @since 1.0.2
459 */
460Yii.CComponent.prototype.attachBehavior = function (name, behavior) {
461		if(!(behavior instanceof Yii.CBehavior)) {
462			behavior=Yii.createComponent(behavior);
463		}
464		behavior.setEnabled(true);
465		behavior.attach(this);
466		if (this._m === null) {
467			this._m = {};
468		}
469		return (this._m[name]=behavior);
470	};
471/**
472 * Detaches a behavior from the component.
473 * The behavior's {@link IBehavior::detach} method will be invoked.
474 * @param {String} name the behavior's name. It uniquely identifies the behavior.
475 * @returns {IBehavior} the detached behavior. Null if the behavior does not exist.
476 * @since 1.0.2
477 */
478Yii.CComponent.prototype.detachBehavior = function (name) {
479		var behavior;
480		if(this._m[name] !== undefined) {
481			this._m[name].detach(this);
482			behavior=this._m[name];
483			delete this._m[name];
484			return behavior;
485		}
486	};
487/**
488 * Enables all behaviors attached to this component.
489 * @since 1.0.2
490 */
491Yii.CComponent.prototype.enableBehaviors = function () {
492		var i, behavior;
493		if(this._m!==null) {
494			for (i in this._m) {
495				if (this._m.hasOwnProperty(i)) {
496					behavior = this._m[i];
497					behavior.setEnabled(true);
498				}
499			}
500		}
501	};
502/**
503 * Disables all behaviors attached to this component.
504 * @since 1.0.2
505 */
506Yii.CComponent.prototype.disableBehaviors = function () {
507		var i, behavior;
508		if(this._m!==null) {
509			for (i in this._m) {
510				if (this._m.hasOwnProperty(i)) {
511					behavior = this._m[i];
512					behavior.setEnabled(false);
513				}
514			}
515		}
516	};
517/**
518 * Enables an attached behavior.
519 * A behavior is only effective when it is enabled.
520 * A behavior is enabled when first attached.
521 * @param {String} name the behavior's name. It uniquely identifies the behavior.
522 * @since 1.0.2
523 */
524Yii.CComponent.prototype.enableBehavior = function (name) {
525		if(this._m !== null && this._m[name] !== undefined) {
526			this._m[name].setEnabled(true);
527		}
528	};
529/**
530 * Disables an attached behavior.
531 * A behavior is only effective when it is enabled.
532 * @param {String} name the behavior's name. It uniquely identifies the behavior.
533 * @since 1.0.2
534 */
535Yii.CComponent.prototype.disableBehavior = function (name) {
536		if(this._m !== null && this._m[name] !== undefined) {
537			this._m[name].setEnabled(false);
538		}
539	};
540/**
541 * Determines whether a property is defined.
542 * A property is defined if there is a getter or setter method
543 * defined in the class. Note, property names are case-insensitive.
544 * @param {String} name the property name
545 * @returns {Boolean} whether the property is defined
546 * @see canGetProperty
547 * @see canSetProperty
548 */
549Yii.CComponent.prototype.hasProperty = function (name) {
550		return this[name] !== undefined || php.method_exists(this,'get'+php.ucfirst(name)) || php.method_exists(this,'set'+php.ucfirst(name));
551	};
552/**
553 * Determines whether a property can be read.
554 * A property can be read if the class has a getter method
555 * for the property name. Note, property name is case-insensitive.
556 * @param {String} name the property name
557 * @returns {Boolean} whether the property can be read
558 * @see canSetProperty
559 */
560Yii.CComponent.prototype.canGetProperty = function (name) {
561		return this[name] !== undefined || php.method_exists(this,'get'+php.ucfirst(name));
562	};
563/**
564 * Determines whether a property can be set.
565 * A property can be written if the class has a setter method
566 * for the property name. Note, property name is case-insensitive.
567 * @param {String} name the property name
568 * @returns {Boolean} whether the property can be written
569 * @see canGetProperty
570 */
571Yii.CComponent.prototype.canSetProperty = function (name) {
572		return this[name] !== undefined || php.method_exists(this,'set'+php.ucfirst(name));
573	};
574/**
575 * Determines whether an event is defined.
576 * An event is defined if the class has a method named like 'onXXX'.
577 * Note, event name is case-insensitive.
578 * @param {String} name the event name
579 * @returns {Boolean} whether an event is defined
580 */
581Yii.CComponent.prototype.hasEvent = function (name) {
582		return !php.strncasecmp(name,'on',2) && php.method_exists(this,name);
583	};
584/**
585 * Checks whether the named event has attached handlers.
586 * @param {String} name the event name
587 * @returns {Boolean} whether an event has been attached one or several handlers
588 */
589Yii.CComponent.prototype.hasEventHandler = function (name) {
590		
591		return this._e !== null && this._e[name] !== undefined && this._e[name].getCount()>0;
592	};
593/**
594 * Returns the list of attached event handlers for an event.
595 * @param {String} name the event name
596 * @returns {Yii.CList} list of attached event handlers for the event
597 * @throws {Yii.CException} if the event is not defined
598 */
599Yii.CComponent.prototype.getEventHandlers = function (name) {
600		if(this.hasEvent(name))	{
601			
602			if (this._e === null) {
603				this._e = {};
604			}
605			if(this._e[name] === undefined) {
606				this._e[name]=new Yii.CList();
607			}
608			return this._e[name];
609		}
610		else {
611			throw new Yii.CException(Yii.t('yii','Event "{class}.{event}" is not defined.',
612				{'{class}':this.getClassName(), '{event}':name}));
613		}
614	};
615/**
616 * Attaches an event handler to an event.
617 * 
618 * An event handler must be a valid PHP callback, i.e., a string referring to
619 * a global function name, or an array containing two elements with
620 * the first element being an object and the second element a method name
621 * of the object.
622 * 
623 * An event handler must be defined with the following signature,
624 * <pre>
625 * function handlerName(event) {}
626 * </pre>
627 * where $event includes parameters associated with the event.
628 * 
629 * This is a convenient method of attaching a handler to an event.
630 * It is equivalent to the following code:
631 * <pre>
632 * component.getEventHandlers(eventName).add(eventHandler);
633 * </pre>
634 * 
635 * Using {@link getEventHandlers}, one can also specify the excution order
636 * of multiple handlers attaching to the same event. For example:
637 * <pre>
638 * component.getEventHandlers(eventName).insertAt(0,eventHandler);
639 * </pre>
640 * makes the handler to be invoked first.
641 * 
642 * @param {String} name the event name
643 * @param {Yii.Callback} handler the event handler
644 * @throws {Yii.CException} if the event is not defined
645 * @see detachEventHandler
646 */
647Yii.CComponent.prototype.attachEventHandler = function (name, handler) {
648		this.getEventHandlers(name).add(handler);
649	};
650/**
651 * Detaches an existing event handler.
652 * This method is the opposite of {@link attachEventHandler}.
653 * @param {String} name event name
654 * @param {Yii.Callback} handler the event handler to be removed
655 * @returns {Boolean} if the detachment process is successful
656 * @see attachEventHandler
657 */
658Yii.CComponent.prototype.detachEventHandler = function (name, handler) {
659		if(this.hasEventHandler(name)) {
660			return this.getEventHandlers(name).remove(handler)!==false;
661		}
662		else {
663			return false;
664		}
665	};
666/**
667 * Raises an event.
668 * This method represents the happening of an event. It invokes
669 * all attached handlers for the event.
670 * @param {String} name the event name
671 * @param {Yii.CEvent} event the event parameter
672 * @throws {Yii.CException} if the event is undefined or an event handler is invalid.
673 */
674Yii.CComponent.prototype.raiseEvent = function (name, event) {
675		var i, handler, object, method, limit;
676		if(this._e !== null && this._e[name] !== undefined)	{
677			limit = this._e[name].length;
678			for (i = 0; i < limit; i++) {
679				handler = this._e[name][i];
680				if(typeof(handler) === 'string') {
681					php.call_user_func(handler,event);
682				}
683				if(Object.prototype.toString.call(handler) === '[object Array]') {
684					// an array: 0 - object, 1 - method name
685					object = handler[0];
686					method = handler[1];
687					
688					if(typeof(object) === 'string') {	// static method call
689						php.call_user_func(handler,event);
690					}
691					else if(php.method_exists(object,method)) {
692				
693						object[method](event);
694					}
695					else {
696						throw new Yii.CException(Yii.t('yii','Event "{class}.{event}" is attached with an invalid handler "{handler}".',
697							{'{class}':this.getClassName(), '{event}':name, '{handler}':handler[1]}));
698					}
699				}
700				else if (typeof handler === "function") { // callback function
701					php.call_user_func(handler,event);
702				}
703				else {
704					console.log(i);
705					console.log(name);
706					console.log(handler);
707					throw new Yii.CException(Yii.t('yii','Event "{class}.{event}" is attached with an invalid handler "{handler}".',
708						{'{class}':this.getClassName(), '{event}':name, '{handler}':handler}));
709				}
710				// stop further handling if param.handled is set true
711				if((event instanceof Yii.CEvent) && event.handled) {
712					return;
713				}
714				
715			}
716		}
717		else if(YII_DEBUG && !this.hasEvent(name)) {
718			throw new Yii.CException(Yii.t('yii','Event "{class}.{event}" is not defined.',
719				{'{class}':this.getClassName(), '{event}':name}));
720		}
721	};
722/**
723 * Evaluates a PHP expression or callback under the context of this component.
724 * 
725 * Valid PHP callback can be class method name in the form of
726 * array(ClassName/Object, MethodName), or anonymous function (only available in PHP 5.3.0 or above).
727 * 
728 * If a PHP callback is used, the corresponding function/method signature should be
729 * <pre>
730 * function foo(param1, param2, +++, component) { +++ }
731 * </pre>
732 * where the array elements in the second parameter to this method will be passed
733 * to the callback as $param1, $param2, ...; and the last parameter will be the component itself.
734 * 
735 * If a PHP expression is used, the second parameter will be "extracted" into PHP variables
736 * that can be directly accessed in the expression. See {@link http://us.php.net/manual/en/function.extract.php PHP extract}
737 * for more details. In the expression, the component object can be accessed using $this.
738 * 
739 * @param {Mixed} _expression_ a PHP expression or PHP callback to be evaluated.
740 * @param {Array} _data_ additional parameters to be passed to the above expression/callback.
741 * @returns {Mixed} the expression result
742 * @since 1.1.0
743 */
744Yii.CComponent.prototype.evaluateExpression = function (_expression_, _data_) {
745		if (_data_ === undefined) {
746			_data_ = [];
747		}
748		if(typeof(_expression_) === 'string')
749		{
750			php.extract(_data_);
751			return eval('return '+_expression_+';');
752		}
753		else
754		{
755			_data_.push(this);
756			return php.call_user_func_array(_expression_, _data_);
757		}
758	}