/** * @author Pavel Yaschenko */ (function ($, richfaces, params) { richfaces.blankFunction = function () { }; //TODO: add it to global library /** * @class Base class for all components. * All RichFaces components should use this class as base or another RichFaces class which based on it. *

     //Inheritance example:
     (function ($, richfaces, params) {

     // Constructor definition
     richfaces.MyComponent = function(componentId, [options]) {
     // call constructor of parent class
     $super.constructor.call(this, componentId, [options]);

     
     // call this.attachToDom method to attach component to dom element
     // its required for the client side API calls and to clean up after ajax request or page unload:
     // destroy method will be called if component attached to dom
     this.attachToDom(componentId);
     
     };

     // define private method
     var myPrivateMethod = function () {
     }

     // Extend component class and add protected methods from parent class to our container
     richfaces.BaseComponent.extend(richfaces.BaseComponent, richfaces.MyComponent);

     // define super class link
     var $super = richfaces.MyComponent.$super;

     // Add new properties and methods
     $.extend(richfaces.MyComponent.prototype, (function (params) {
     return {
     name:"MyComponent",
     f:function (){alert("hello"),
     // destroy method definition for clean up
     destroy: function () {
     // clean up code here

     // call parent's destroy method
     $super.destroy.call(this);
     }
     }
     };
     })(params));
     })(jQuery, RichFaces);
     
* * @memberOf RichFaces * @name BaseComponent * * @constructor * @param {String} componentId - component id * */ richfaces.BaseComponent = function(componentId) { this.id = componentId; this.options = this.options || {}; }; var $p = {}; var extend = function (parent, child, h) { h = h || {}; var F = richfaces.blankFunction; F.prototype = parent.prototype; child.prototype = new F(); child.prototype.constructor = child; child.$super = parent.prototype; if (child.$super == richfaces.BaseComponent.prototype) { var r = jQuery.extend({}, $p, h || {}); } var _parent = child; // create wrapper with protected methods and variables child.extend = function (_child, _h) { _h = _h || {}; var _r = jQuery.extend({}, r || h || {}, _h || {}); return extend(_parent, _child, _r); } return r || h; }; /** * Method extends child class prototype with parent prototype * and return the object with parent's protected methods * * @function * @name RichFaces.BaseComponent.extend * * @return {object} * */ richfaces.BaseComponent.extend = function(child, h) { return extend(richfaces.BaseComponent, child, h); }; /** * Easy way to create a subclass. * * Example: * * RichFaces.ui.MyClass = RichFaces.BaseComponent.extendClass({ * // Class name * name: "MyClass", * * // Constructor * init : function (...) { * // ... * }, * * // public api * publicFunction : function () { * // ... * }, * * // private api * // names of private methods should start with '__' (2 underscore symbols) * __privateFunction : function () { * // ... * }, * * __overrideMethod : function () { * // if you need to use method from parent class use link to parent prototype * // like in previous solution with extend method * $super.__overrideMethod.call(this, ...params...); * * //... * } * * }); * * RichFaces.ui.MySecondClass = RichFaces.ui.MyClass({ * // * name : "MySecondClass", * * // Constructor * init : function (...) { * // ... * } * * }) * * */ richfaces.BaseComponent.extendClass = function (methods) { var DerivedClass = methods.init || richfaces.blankFunction; var SupperClass = this; SupperClass.extend(DerivedClass); DerivedClass.extendClass = SupperClass.extendClass; $.extend(DerivedClass.prototype, methods); return DerivedClass; }; $.extend(richfaces.BaseComponent.prototype, (function (params) { return { /** * Component name. * * @name RichFaces.BaseComponent#name * @type String * */ name: "BaseComponent", /** * Method for converting object to string * * @function * @name RichFaces.BaseComponent#toString * * @return {String} * */ toString: function() { var result = []; if (this.constructor.$super) { result[result.length] = this.constructor.$super.toString(); } result[result.length] = this.name; return result.join(', '); }, /** TODO: add jsdocs and qunit tests * */ getValue: function() { return; }, /** * Method returns element's id for event handlers binding. * Event API calls this method when binding by component object as selector was used. * * @function * @name RichFaces.BaseComponent#getEventElement * * @return {String} * */ getEventElement: function() { return this.id; }, /** * Attach component object to DOM element by component id, DOM element or jQuery object and returns the element * Its required for the client side API calls and to clean up after ajax request or document unload by * calling destroy method * * @function * @name RichFaces.BaseComponent#attachToDom * @param {string|DOMElement|jQuery} source - component id, DOM element or DOM elements wrapped by jQuery * * @return {DOMElement} * */ attachToDom: function(source) { source = source || this.id; var element = richfaces.getDomElement(source); if (element) { var container = element[richfaces.RICH_CONTAINER] = element[richfaces.RICH_CONTAINER] || {}; container.component = this; } return element; }, /** * Detach component object from DOM element by component id, DOM element or jQuery object * * @function * @name RichFaces.BaseComponent#detach * @param {string|DOMElement|jQuery} source - component id, DOM element or DOM elements wrapped by jQuery * * */ detach: function(source) { source = source || this.id; var element = richfaces.getDomElement(source); element && element[richfaces.RICH_CONTAINER] && (element[richfaces.RICH_CONTAINER].component = null); }, /** * Invokes event on on the DOM element * @param eventType event type, e.g. "click" * @param element DOM element object * @param event jQuery Event * @param data additional data used for event handler * @return true if an event is successfully invoked */ invokeEvent: function(eventType, element, event, data) { var handlerResult, result; var eventObj = $.extend({}, event, {type: eventType}); if (!eventObj) { if (document.createEventObject) { eventObj = document.createEventObject(); eventObj.type = eventType; } else if (document.createEvent) { eventObj = document.createEvent('Events'); eventObj.initEvent(eventType, true, false); } } eventObj[richfaces.RICH_CONTAINER] = {component:this, data: data}; var eventHandler = this.options['on' + eventType]; if (typeof eventHandler == "function") { handlerResult = eventHandler.call(element, eventObj); } if (richfaces.Event) { result = richfaces.Event.callHandler(this, eventType, data); } if (result != false && handlerResult != false) result = true; return result; }, /** * Destroy method. Will be called before remove component from the page * * @function * @name RichFaces.BaseComponent#destroy * * */ destroy: function() { } }; })(params)); richfaces.BaseNonVisualComponent = function(componentId) { this.id = componentId; this.options = this.options || {}; }; richfaces.BaseNonVisualComponent.extend = function(child, h) { return extend(richfaces.BaseNonVisualComponent, child, h); }; richfaces.BaseNonVisualComponent.extendClass = function (methods) { var DerivedClass = methods.init || richfaces.blankFunction; var SupperClass = this; SupperClass.extend(DerivedClass); DerivedClass.extendClass = SupperClass.extendClass; $.extend(DerivedClass.prototype, methods); return DerivedClass; }; $.extend(richfaces.BaseNonVisualComponent.prototype, (function (params) { return { name: "BaseNonVisualComponent", toString: function() { var result = []; if (this.constructor.$super) { result[result.length] = this.constructor.$super.toString(); } result[result.length] = this.name; return result.join(', '); }, getValue: function() { return; }, /** * Attach component object to DOM element by component id, DOM element or jQuery object and returns the element * Its required for the client side API calls and to clean up after ajax request or document unload by * calling destroy method * * @function * @name RichFaces.BaseNonVisualComponent#attachToDom * @param {string|DOMElement|jQuery} source - component id, DOM element or DOM elements wrapped by jQuery * * @return {DOMElement} * */ attachToDom: function(source) { source = source || this.id; var element = richfaces.getDomElement(source); if (element) { var container = element[richfaces.RICH_CONTAINER] = element[richfaces.RICH_CONTAINER] || {}; if (container.attachedComponents) { container.attachedComponents[this.name] = this; } else { container.attachedComponents = {}; container.attachedComponents[this.name] = this; } } return element; }, /** * Detach component object from DOM element by component id, DOM element or jQuery object * * @function * @name RichFaces.BaseNonVisualComponent#detach * @param {string|DOMElement|jQuery} source - component id, DOM element or DOM elements wrapped by jQuery * * */ detach: function(source) { source = source || this.id; var element = richfaces.getDomElement(source); element && element[richfaces.RICH_CONTAINER] && (element[richfaces.RICH_CONTAINER].attachedComponents[this.name] = null); }, /** * Destroy method. Will be called before remove component from the page * * @function * @name RichFaces.BaseNonVisualComponent#destroy * * */ destroy: function() { } }; })(params)); })(jQuery, window.RichFaces || (window.RichFaces = {})); // RichFaces Base class for ui components (function($, rf) { rf.ui = rf.ui || {}; // Constructor definition rf.ui.Base = function(componentId, options, defaultOptions) { this.namespace = "." + rf.Event.createNamespace(this.name, componentId); // call constructor of parent class $super.constructor.call(this, componentId); this.options = $.extend(this.options, defaultOptions, options); this.attachToDom(); this.__bindEventHandlers(); }; // Extend component class and add protected methods from parent class to our container rf.BaseComponent.extend(rf.ui.Base); // define super class link var $super = rf.ui.Base.$super; $.extend(rf.ui.Base.prototype, { __bindEventHandlers: function () { }, destroy: function () { rf.Event.unbindById(this.id, this.namespace); $super.destroy.call(this); } }); })(jQuery, window.RichFaces || (window.RichFaces = {}));