/** * @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 = {}));