From ac18b6cc8dac0cb751af1f76ca30bf49ef348c3d Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 20 Mar 2014 09:40:37 +0000 Subject: [PATCH] changed et2_core_inheritance.js to implement ClassWithAttributes extending Class from egw_inheritance and changed et2 objects to use ClassWithAttributes when required (also fixed lots of IDE warnings / added docu) --- etemplate/js/et2_core_DOMWidget.js | 2 +- etemplate/js/et2_core_arrayMgr.js | 2 +- etemplate/js/et2_core_inheritance.js | 417 ++---------------- etemplate/js/et2_core_interfaces.js | 20 +- etemplate/js/et2_core_widget.js | 4 +- etemplate/js/et2_dataview.js | 22 +- etemplate/js/et2_dataview_controller.js | 32 +- .../js/et2_dataview_controller_selection.js | 10 +- etemplate/js/et2_dataview_model_columns.js | 26 +- etemplate/js/et2_dataview_view_container.js | 65 +-- etemplate/js/et2_dataview_view_rowProvider.js | 10 +- .../js/et2_extension_nextmatch_dynheight.js | 12 +- .../js/et2_extension_nextmatch_rowProvider.js | 56 ++- etemplate/js/etemplate2.js | 5 +- etemplate/js/test/test_dataview.html | 3 +- phpgwapi/js/jsapi/app_base.js | 7 + phpgwapi/js/jsapi/egw_core.js | 46 +- phpgwapi/js/jsapi/egw_inheritance.js | 93 ++-- phpgwapi/js/jsapi/egw_lang.js | 21 +- phpgwapi/js/jsapi/egw_links.js | 13 +- 20 files changed, 295 insertions(+), 571 deletions(-) diff --git a/etemplate/js/et2_core_DOMWidget.js b/etemplate/js/et2_core_DOMWidget.js index 85c088ff1d..a94f8158fe 100644 --- a/etemplate/js/et2_core_DOMWidget.js +++ b/etemplate/js/et2_core_DOMWidget.js @@ -503,7 +503,7 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, * * @augments Class */ -var et2_surroundingsMgr = Class.extend( +var et2_surroundingsMgr = ClassWithAttributes.extend( { /** * Constructor diff --git a/etemplate/js/et2_core_arrayMgr.js b/etemplate/js/et2_core_arrayMgr.js index 00122997fe..9aa1b4f531 100644 --- a/etemplate/js/et2_core_arrayMgr.js +++ b/etemplate/js/et2_core_arrayMgr.js @@ -14,7 +14,7 @@ /*egw:uses et2_core_common; - et2_core_inheritance; + egw_inheritance; et2_core_phpExpressionCompiler; */ diff --git a/etemplate/js/et2_core_inheritance.js b/etemplate/js/et2_core_inheritance.js index 3cf038ed33..6ba9ff2d81 100644 --- a/etemplate/js/et2_core_inheritance.js +++ b/etemplate/js/et2_core_inheritance.js @@ -1,5 +1,5 @@ /** - * EGroupware eTemplate2 - JS code for implementing inheritance + * EGroupware eTemplate2 - JS code for implementing inheritance with attributes * * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License * @package etemplate @@ -14,360 +14,19 @@ /*egw:uses et2_core_common; + egw_inheritance; */ -/** - * Usage of the JS inheritance system - * ---------------------------------- - * - * To create a class write - * - * MyClass = Class.extend([interfaces, ] functions); - * - * where "interfaces" is a single interface or an array of interfaces and - * functions an object containing the functions the class implements. - * - * An interface has to be created in the following way: - * - * var IBreathingObject = new Interface({ - * breath: function() {} - * }); - * - * var Human = Class.extend(IBreathingObject, { - * walk: function() { - * console.log("Walking"); - * }, - * speak: function(_words) { - * console.log(_words); - * } - * }); - * - * As "Human" does not implement the function "breath", "Human" is treated as - * abstract. Trying to create an instance of "Human" will throw an exception. - * However - * - * Human.prototype.implements(IBreathingObject); - * - * will return true. Lets create a specific class of "Human": - * - * var ChuckNorris = Human.extend({ - * breath: function() { - * console.log("Chuck Norris does not breath, he holds air hostage."); - * }, - * speak: function(_words) { - * console.warn("Chuck Norris says:"); - * this._super(_words); - * } - * }); - */ - -// The following code is mostly taken from -// http://ejohn.org/blog/simple-javascript-inheritance/ -// some parts were slightly changed for better understanding. Added possiblity -// to use interfaces. - -/* Simple JavaScript Inheritance - * By John Resig http://ejohn.org/ - * MIT Licensed - */ -// Inspired by base2 and Prototype -(function(){ - var initializing = false; - - /** - * Turn this to "true" to track creation and destruction of elements - */ - var getMem_freeMem_trace = false; - - var tracedObjects = {}; - - // Check whether "function decompilation" works - fnTest is normally used to - // check whether a - var fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; - - // Base "Class" for interfaces - needed to check whether an object is an - // interface - this.Interface = function(fncts) { - for (var key in fncts) - { - this[key] = fncts[key]; - } - }; - - /** - * The addInterfaceFunctions function adds all interface functions the class has - * to implement to the class prototype. - */ - function addInterfaceFunctions(prototype, interfaces) - { - // Remember all interface functions in the prototype - var ifaces = ((typeof prototype["_ifacefuncs"] == "undefined") ? [] : - prototype["_ifacefuncs"]); - - prototype["_ifacefuncs"] = []; - - for (var i = 0; i < interfaces.length; i++) - { - var iface = interfaces[i]; - if (iface instanceof Interface) - { - for (var key in iface) - { - prototype["_ifacefuncs"].push(key); - } - } - else - { - throw("Interfaces must be instance of Interface!"); - } - } - - for (var i = 0; i < ifaces.length; i++) - { - prototype["_ifacefuncs"].push(ifaces[i]); - } - }; - - function addAttributeFunctions(prototype, _super) - { - function _copyMerge(_new, _old) - { - var result = {}; - - // Copy the new object - if (typeof _new != "undefined") - { - for (var key in _new) - { - result[key] = _new[key]; - } - } - - // Merge the old object - for (var key in _old) - { - if (typeof result[key] == "undefined") - { - result[key] = _old[key]; - } - } - - return result; - } - - var attributes = {}; - - // Copy the old attributes - for (var key in prototype.attributes) - { - attributes[key] = _copyMerge({}, prototype.attributes[key]); - } - - // Add the old attributes to the new ones. If the attributes already - // exist, they are merged. - for (var key in _super.attributes) - { - var _old = _super.attributes[key]; - var _new = {}; - - attributes[key] = _copyMerge(attributes[key], _old); - } - - // Validate the attributes - for (var key in attributes) - { - et2_validateAttrib(key, attributes[key]); - } - - prototype.attributes = attributes; - }; - - function classExtend(interfaces, prop) { - - if (typeof prop == "undefined") - { - prop = interfaces; - interfaces = []; - } - - // If a single interface is given, encapsulate it in an array - if (!(interfaces instanceof Array)) - { - interfaces = [interfaces]; - } - - if (typeof prop.attributes == "undefined") - { - prop.attributes = {}; - } - - var _super = this.prototype; - - // Instantiate a base class (but only create the instance, - // don't run the init constructor) - initializing = true; - var prototype = new this(); - initializing = false; - - // Copy the properties over onto the new prototype - for (var name in prop) { - // Check if we're overwriting an existing function and check whether - // the function actually uses "_super" - the RegExp test function - // silently converts the funciton prop[name] to a string. - if (typeof prop[name] == "function" && - typeof _super[name] == "function" && fnTest.test(prop[name])) - { - prototype[name] = (function(name, fn){ - return function() { - var tmp = this._super; - - // Add a new ._super() method that is the same method - // but on the super-class - this._super = _super[name]; - - // The method only need to be bound temporarily, so we - // remove it when we're done executing - var ret = fn.apply(this, arguments); - this._super = tmp; - - return ret; - }; - })(name, prop[name]); - } - else - { - prototype[name] = prop[name]; - } - } - - // Add the interface functions and the "implements" function to the - // prototype - addInterfaceFunctions(prototype, interfaces); - - // Merge the attributes and create the functions corresponding to the - // attributes - addAttributeFunctions(prototype, _super); - - // The dummy class constructor - function Class() { - // All construction is actually done in the init method - if (!initializing) - { - // Check whether the object implements all interface functions - for (var i = 0; i < this._ifacefuncs.length; i++) - { - var func = this._ifacefuncs[i]; - if (!(typeof this[func] == "function")) - { - throw("Trying to create abstract object, interface " + - "function '" + func + "' not implemented."); - } - } - - // Do some tracing of the getMem_freeMem_trace is activated - if (getMem_freeMem_trace) - { - this.__OBJ_UID = "obj_" + egw.uid(); - var className = this.className(); - tracedObjects[this.__OBJ_UID] = { - "created": new Date().getTime(), - "class": className - } - egw.debug("log", "*" + this.__OBJ_UID + " (" + className + ")"); - } - - if (this.init) - { - this.init.apply(this, arguments); - } - } - } - - // Populate our constructed prototype object - Class.prototype = prototype; - - // Enforce the constructor to be what we expect - Class.prototype.constructor = Class; - - // And make this class extendable - Class.extend = classExtend; - - return Class; - }; - - // The base Class implementation (does nothing) - this.Class = function(){}; - - // Create a new Class that inherits from this class. The first parameter - // is an array which defines a set of interfaces the object has to - // implement. An interface is simply an object with named functions. - Class.extend = classExtend; - - // The base class has no attributes - Class.prototype.attributes = {}; - - // Add the basic functions - - /** - * Destructor function - it calls "destroy" if it has been defined and then - * deletes all keys of this element, so that any access to this element will - * eventually throw an exception, making it easier to hunt down memory leaks. - */ - Class.prototype.free = function() { - if (this.destroy) - { - this.destroy(); - } - - // Trace the freeing of the object - if (getMem_freeMem_trace) - { - delete(tracedObjects[this.__OBJ_UID]); - egw.debug("log", "-" + this.__OBJ_UID); - } - - // Delete every object entry - for (var key in this) - { - delete(this[key]); - } - - // Don't raise an exception when attempting to free an element multiple - // times. - this.free = function() {}; - }; - - // Some debug functions for memory leak hunting - if (getMem_freeMem_trace) - { - /** - * Prints a list of all objects UIDs which have not been freed yet. - */ - Class.prototype.showTrace = function() { - console.log(tracedObjects); - }, - - /** - * VERY slow - for debugging only! - */ - Class.prototype.className = function() { - for (var key in window) - { - if (key.substr(0, 3) == "et2" && this.constructor == window[key]) - { - return key; - } - } - - return "?"; - } - } - +var ClassWithAttributes = Class.extend( +{ /** * Returns the value of the given attribute. If the property does not * exist, an error message is issued. + * + * @param {string} _name + * @return {*} */ - Class.prototype.getAttribute = function(_name) { + getAttribute: function(_name) { if (typeof this.attributes[_name] != "undefined" && !this.attributes[_name].ignore) { @@ -384,15 +43,19 @@ { egw.debug("error", this, "Attribute '" + _name + "' does not exist!"); } - }; + }, /** * The setAttribute function sets the attribute with the given name to * the given value. _override defines, whether this[_name] will be set, * if this key already exists. _override defaults to true. A warning * is issued if the attribute does not exist. + * + * @param {string} _name + * @param {*} _value + * @param {boolean} _override */ - Class.prototype.setAttribute = function(_name, _value, _override) { + setAttribute: function(_name, _value, _override) { if (typeof this.attributes[_name] != "undefined") { if (!this.attributes[_name].ignore) @@ -419,16 +82,16 @@ { egw.debug("warn", this, "Attribute '" + _name + "' does not exist!"); } - }; + }, /** * generateAttributeSet sanitizes the given associative array of attributes * (by passing each entry to "et2_checkType" and checking for existance of * the attribute) and adds the default values to the associative array. * - * @param _attrs is the associative array containing the attributes. + * @param {object} _attrs is the associative array containing the attributes. */ - Class.prototype.generateAttributeSet = function(_attrs) { + generateAttributeSet: function(_attrs) { // Sanity check and validation for (var key in _attrs) @@ -466,15 +129,17 @@ } return _attrs; - }; + }, /** * The initAttributes function sets the attributes to their default * values. The attributes are not overwritten, which means, that the * default is only set, if either a setter exists or this[propName] does * not exist yet. + * + * @param {object} _attrs is the associative array containing the attributes. */ - Class.prototype.initAttributes = function(_attrs) { + initAttributes: function(_attrs) { for (var key in _attrs) { if (typeof this.attributes[key] != "undefined" && !this.attributes[key].ignore && !(_attrs[key] == undefined)) @@ -482,38 +147,14 @@ this.setAttribute(key, _attrs[key], false); } } - }; + }, - /** - * The implements function can be used to check whether the object - * implements the given interface. - */ - Class.prototype.implements = function(_iface) { - for (var key in _iface) + _validate_attributes: function(attributes) + { + // Validate the attributes + for (var key in attributes) { - if (this._ifacefuncs.indexOf(key) < 0) - { - return false; - } + et2_validateAttrib(key, attributes[key]); } - return true; - }; - - /** - * The instanceOf function can be used to check for both - classes and - * interfaces. Please don't change the case of this function as this - * affects IE and Opera support. - */ - Class.prototype.instanceOf = function(_obj) { - if (_obj instanceof Interface) - { - return this.implements(_obj); - } - else - { - return this instanceof _obj; - } - }; - -}).call(window); - + } +}); \ No newline at end of file diff --git a/etemplate/js/et2_core_interfaces.js b/etemplate/js/et2_core_interfaces.js index 32c0760d9a..15a5a98d22 100644 --- a/etemplate/js/et2_core_interfaces.js +++ b/etemplate/js/et2_core_interfaces.js @@ -24,11 +24,11 @@ var et2_IDOMNode = new Interface({ * Returns the DOM-Node of the current widget. The return value has to be * a plain DOM node. If you want to return an jQuery object as you receive * it with - * + * * obj = $j(node); - * + * * simply return obj[0]; - * + * * @param _sender The _sender parameter defines which widget is asking for * the DOMNode. Depending on that, the widget may return different nodes. * This is used in the grid. Normally the _sender parameter can be omitted @@ -58,19 +58,19 @@ var et2_IInput = new Interface({ * Causes the dirty flag to be reseted. */ resetDirty: function() {}, - + /** * Checks the data to see if it is valid, as far as the client side can tell. * Return true if it's not possible to tell on the client side, because the server * will have the chance to validate also. - * + * * The messages array is to be populated with everything wrong with the data, * so don't stop checking after the first problem unless it really makes sense * to ignore other problems. - * - * @param {String[]} messages List of messages explaining the failure(s). + * + * @param {String[]} messages List of messages explaining the failure(s). * messages should be fairly short, and already translated. - * + * * @return {boolean} True if the value is valid (enough), false to fail */ isValid: function(messages) {} @@ -101,7 +101,7 @@ var et2_ISubmitListener = new Interface({ /** * Called whenever the template gets submitted. Return false if you want to * stop submission. - * + * * @param _values contains the values which will be sent to the server. * Listeners may change these values before they get submitted. */ @@ -119,6 +119,8 @@ var et2_IDetachedDOM = new Interface({ * Creates a list of attributes which can be set when working in the * "detached" mode. The result is stored in the _attrs array which is provided * by the calling code. + * + * @param {array} _attrs */ getDetachedAttributes: function(_attrs) {}, diff --git a/etemplate/js/et2_core_widget.js b/etemplate/js/et2_core_widget.js index 5cef65f406..5a9b891f98 100644 --- a/etemplate/js/et2_core_widget.js +++ b/etemplate/js/et2_core_widget.js @@ -102,9 +102,9 @@ function et2_createWidget(_name, _attrs, _parent) /** * The et2 widget base class. * - * @augments Class + * @augments ClassWithAttributes */ -var et2_widget = Class.extend( +var et2_widget = ClassWithAttributes.extend( { attributes: { "id": { diff --git a/etemplate/js/et2_dataview.js b/etemplate/js/et2_dataview.js index 95199c03f8..a3c78c0692 100644 --- a/etemplate/js/et2_dataview.js +++ b/etemplate/js/et2_dataview.js @@ -28,7 +28,7 @@ * header, etc.) and contains the root container: an instance of * et2_dataview_view_grid, which can be accessed using the "grid" property of * this object. - * + * * @augments Class */ var et2_dataview = Class.extend({ @@ -55,7 +55,9 @@ var et2_dataview = Class.extend({ /** * Constructor for the grid container - * @param object _parentNode is the DOM-Node into which the grid view will be inserted + * + * @param {DOMElement} _parentNode is the DOM-Node into which the grid view will be inserted + * @param {egw} _egw * @memberOf et2_dataview */ init: function(_parentNode, _egw) { @@ -158,7 +160,7 @@ var et2_dataview = Class.extend({ resize: function(_w, _h) { // Not fully initialized yet... if (!this.columnMgr) return; - + if (this.width != _w) { this.width = _w; @@ -192,7 +194,7 @@ var et2_dataview = Class.extend({ /** * Recalculates the stylesheets which determine the column visibility and * width. - * + * * @param setDefault boolean Allow admins to save current settings as default for all users */ updateColumns: function(setDefault) { @@ -297,11 +299,11 @@ var et2_dataview = Class.extend({ this.visibleColumnCount++; // Update the visibility of the column - this.egw.css("." + col.tdClass, - "display: table-cell; " + + this.egw.css("." + col.tdClass, + "display: table-cell; " + "!important;"); - // Ugly browser dependant code - each browser seems to treat the + // Ugly browser dependant code - each browser seems to treat the // right (collapsed) border of the row differently var subBorder = 0; var subHBorder = 0; @@ -336,12 +338,12 @@ var et2_dataview = Class.extend({ // Write the width of the header columns var headerWidth = Math.max(0, (col.width - this.headerBorderWidth - subHBorder)); - this.egw.css(".egwGridView_outer ." + col.divClass, + this.egw.css(".egwGridView_outer ." + col.divClass, "width: " + headerWidth + "px;"); // Write the width of the body-columns var columnWidth = Math.max(0, (col.width - this.columnBorderWidth - subBorder)); - this.egw.css(".egwGridView_grid ." + col.divClass, + this.egw.css(".egwGridView_grid ." + col.divClass, "width: " + columnWidth + "px;"); totalWidth += col.width; @@ -486,7 +488,7 @@ var et2_dataview = Class.extend({ * Reads the scrollbar width */ _getScrollbarWidth: function(_table) { - // Create a temporary td and two divs, which are inserted into the + // Create a temporary td and two divs, which are inserted into the // DOM-Tree. The outer div has a fixed size and "overflow" set to auto. // When the second div is inserted, it will be forced to display a scrollbar. var div_inner = $j(document.createElement("div")) diff --git a/etemplate/js/et2_dataview_controller.js b/etemplate/js/et2_dataview_controller.js index 88c9bce4ee..5a87b7be11 100644 --- a/etemplate/js/et2_dataview_controller.js +++ b/etemplate/js/et2_dataview_controller.js @@ -49,7 +49,7 @@ var et2_dataview_controller = Class.extend({ * requesting action links for a row. The row data, the index of the row and * the uid are passed as parameters to the function. * uid is passed to the function. - * @param _context is the context in which the _rowCallback and the + * @param _context is the context in which the _rowCallback and the * _linkCallback are called. * @param _actionObjectManager is the object that manages the action * objects. @@ -64,7 +64,7 @@ var et2_dataview_controller = Class.extend({ this._rowCallback = _rowCallback; this._linkCallback = _linkCallback; this._context = _context; - + // Initialize list of child controllers this._children = []; @@ -91,7 +91,7 @@ var et2_dataview_controller = Class.extend({ this._makeIndexVisible, this ); - + // Record the child if(this._parentController != null) { @@ -106,7 +106,7 @@ var et2_dataview_controller = Class.extend({ // Clear the selection timeout this._clearTimer(); - + // Remove the child from the child list if(this._parentController != null) { @@ -125,7 +125,7 @@ var et2_dataview_controller = Class.extend({ * The update function queries the server for changes in the currently * managed index range -- those changes are then merged into the current * view without a complete rebuild of every row. - * + * * @param {boolean} clear Skip the fancy stuff, dump everything and start again. * Completely clears the grid and selection. */ @@ -147,7 +147,7 @@ var et2_dataview_controller = Class.extend({ // Free selection manager this._selectionMgr.clear(); - + // Clear the map this._indexMap = {} // Update selection manager, it uses this by reference @@ -211,7 +211,7 @@ var et2_dataview_controller = Class.extend({ { // Skip any extra keys if(typeof data[key] != "object" || data[key] == null || typeof data[key][uid_key] == "undefined") continue; - + // Add to row / uid map var entry = this._getIndexEntry(idx++); entry.uid = data[key][uid_key]+""; @@ -252,7 +252,7 @@ var et2_dataview_controller = Class.extend({ /** * Returns the row information of the passed node, or null if not available - * + * * @param {DOMNode} node * @return {string|false} UID, or false if not found */ @@ -260,7 +260,7 @@ var et2_dataview_controller = Class.extend({ // Whatever the node, find a TR var row_node = $j(node).closest('tr'); var row = false - + // Check index map - simple case var indexed = this._getIndexEntry(row_node.index()); if(indexed && indexed.row && indexed.row.getDOMNode() == row_node[0]) @@ -280,7 +280,7 @@ var et2_dataview_controller = Class.extend({ } } } - + // Check children for(var i = 0; !row && i < this._children.length; i++) { @@ -612,7 +612,7 @@ var et2_dataview_controller = Class.extend({ { $j(tr).addClass("subentry"); $j("td:first",tr).children("div").last().addClass("level_" + d + " indentation"); - + if(this.entry.idx == 0) { // Set the CSS for the level - required so columns line up @@ -811,7 +811,7 @@ var et2_dataview_controller = Class.extend({ _fetchCallback: function (_response) { this.self._lastModification = _response.lastModification; - + // Do nothing if _response.order evaluates to false if (!_response.order) { @@ -834,7 +834,7 @@ var et2_dataview_controller = Class.extend({ for(var i = this.start; i < this.start + order.length; i++) delete this.self._queue[i]; } - + // Get the current index map for the updated region var idxMap = this.self._getIndexMapping(this.start, order.length); @@ -860,11 +860,11 @@ var et2_dataview_controller = Class.extend({ // Now it's OK to invalidate, if it wasn't before this.self._grid.doInvalidate = true; - + // Update the total element count in the grid this.self._grid.setTotalCount(_response.total); this.self._selectionMgr.setTotalCount(_response.total); - + // Schedule an invalidate, in case total is the same this.self._grid.invalidate(); }, @@ -892,7 +892,7 @@ var et2_dataview_controller = Class.extend({ this._context, {}, 0, - "" + "" ); } this._selectionMgr.registerRow("",0,placeholder.get(0), links); diff --git a/etemplate/js/et2_dataview_controller_selection.js b/etemplate/js/et2_dataview_controller_selection.js index bef117073e..334f0903ac 100644 --- a/etemplate/js/et2_dataview_controller_selection.js +++ b/etemplate/js/et2_dataview_controller_selection.js @@ -24,14 +24,14 @@ * manage an external action object interface for each visible row and proxy all * state changes between an dummy action object, that does no selection handling, * and the external action object interface. - * + * * @augments Class */ var et2_dataview_selectionManager = Class.extend( { /** * Constructor - * + * * @param _parent * @param _indexMap * @param _actionObjectManager @@ -214,10 +214,10 @@ var et2_dataview_selectionManager = Class.extend( this.resetSelection(); this._selectAll = true; - + // Tell action manager to do all this._actionObjectManager.setAllSelected(true); - + // Update the selection for (var key in this._registeredRows) { @@ -519,7 +519,7 @@ var et2_dataview_selectionManager = Class.extend( // Query all unknown ranges from the server for (var i = 0; i < queryRanges.length; i++) { - this._queryRangeCallback.call(this._context, queryRanges[i], + this._queryRangeCallback.call(this._context, queryRanges[i], function (_order) { for (var j = 0; j < _order.length; j++) { diff --git a/etemplate/js/et2_dataview_model_columns.js b/etemplate/js/et2_dataview_model_columns.js index 99910b09c1..cd29c9fec7 100755 --- a/etemplate/js/et2_dataview_model_columns.js +++ b/etemplate/js/et2_dataview_model_columns.js @@ -26,10 +26,10 @@ var ET2_COL_VISIBILITY_ALWAYS_NOSELECT = 3; /** * Class which stores the data of a single column. - * + * * @augments Class */ -var et2_dataview_column = Class.extend({ +var et2_dataview_column = ClassWithAttributes.extend({ attributes: { "id": { @@ -72,7 +72,7 @@ var et2_dataview_column = Class.extend({ /** * Constructor - * + * * @param _attrs * @memberOf et2_dataview_column */ @@ -114,7 +114,7 @@ var et2_dataview_column = Class.extend({ set_visibility: function(_value) { // If visibility is always, don't turn it off if(this.visibility == ET2_COL_VISIBILITY_ALWAYS || this.visibility == ET2_COL_VISIBILITY_ALWAYS_NOSELECT) return; - + if(_value === true) { this.visibility = ET2_COL_VISIBILITY_VISIBLE; @@ -167,6 +167,8 @@ var et2_dataview_columns = Class.extend({ /** * Set the total width of the header row + * + * @param {(string|number)} _width */ setTotalWidth: function(_width) { if (_width != this.totalWidth && _width > 0) @@ -178,6 +180,8 @@ var et2_dataview_columns = Class.extend({ /** * Returns the index of the colum with the given id + * + * @param {string} _id */ getColumnIndexById: function(_id) { for (var i = 0; i < this.columns.length; i++) @@ -192,6 +196,8 @@ var et2_dataview_columns = Class.extend({ /** * Returns the column with the given id + * + * @param {string} _id */ getColumnById: function(_id) { var idx = this.getColumnIndexById(_id); @@ -200,6 +206,8 @@ var et2_dataview_columns = Class.extend({ /** * Returns the width of the column with the given index + * + * @param {number} _idx */ getColumnWidth: function(_idx) { if (this.totalWidth > 0 && _idx >= 0 && _idx < this.columns.length) @@ -262,6 +270,8 @@ var et2_dataview_columns = Class.extend({ /** * Sets a column visiblity set + * + * @param {object} _set */ setColumnVisibilitySet: function(_set) { for (var k in _set) @@ -331,7 +341,7 @@ var et2_dataview_columns = Class.extend({ } } remRelWidth -= fixedTotal / tw; - + // Check whether the width of columns with relative width is larger than their // maxWidth var done; @@ -419,13 +429,13 @@ var et2_dataview_columns = Class.extend({ this.columnWidths.push(w); usedTotal += w; } - + // Deal with any accumulated rounding errors if(usedTotal != tw) { var column, columnIndex; var remaining_width = (usedTotal - tw); - + // Pick the first relative column and use it for(columnIndex = 0; columnIndex < this.columns.length; columnIndex++) { @@ -452,7 +462,7 @@ var et2_dataview_columns = Class.extend({ for(var i = 0; i < this.columns.length; i++) { var col = this.columns[i]; - col.fixedWidth -= Math.round(this.columnWidths[i] / tw * remaining_width) + col.fixedWidth -= Math.round(this.columnWidths[i] / tw * remaining_width); this.columnWidths[i] = Math.max(0, Math.min(col.fixedWidth,tw)); } } diff --git a/etemplate/js/et2_dataview_view_container.js b/etemplate/js/et2_dataview_view_container.js index 3c09eb0e1a..bb4a0e121e 100644 --- a/etemplate/js/et2_dataview_view_container.js +++ b/etemplate/js/et2_dataview_view_container.js @@ -10,7 +10,7 @@ * @version $Id$ */ -"use strict" +"use strict"; /*egw:uses jquery.jquery; @@ -30,10 +30,10 @@ * A container does not know where it resides inside the grid, or whether it is * currently visible or not -- this information is efficiently managed by the * et2_dataview_grid container. - * + * * @augments Class */ -var et2_dataview_container = Class.extend(et2_dataview_IInvalidatable, +var et2_dataview_container = Class.extend(et2_dataview_IInvalidatable, { /** * Initializes the container object. @@ -77,6 +77,9 @@ var et2_dataview_container = Class.extend(et2_dataview_IInvalidatable, * Sets the "destroyCallback" -- the given function gets called whenever * the container is destroyed. This instance is passed as an parameter to * the callback. + * + * @param {function} _callback + * @param {object} _context */ setDestroyCallback: function(_callback, _context) { this._destroyCallback = _callback; @@ -182,6 +185,8 @@ var et2_dataview_container = Class.extend(et2_dataview_IInvalidatable, /** * Removes a certain node from the container + * + * @param {DOMElement} _node */ removeNode: function(_node) { // Get the index of the node in the nodes array @@ -296,6 +301,8 @@ var et2_dataview_container = Class.extend(et2_dataview_IInvalidatable, /** * Sets the top of the element. + * + * @param {number} _value */ setTop: function(_value) { this._top = _value; @@ -303,6 +310,8 @@ var et2_dataview_container = Class.extend(et2_dataview_IInvalidatable, /** * Sets the index of the element. + * + * @param {number} _value */ setIndex: function(_value) { this._index = _value; @@ -355,46 +364,16 @@ var et2_dataview_container = Class.extend(et2_dataview_IInvalidatable, } return true; - } + }, -}); - -/** - * Returns the height of a node in pixels and zero if the element is not - * visible. The height is clamped to positive values. - * The browser switch is placed at this position as the _nodeHeight function is - * one of the most frequently called functions in the whole grid code and should - * stay quite fast. - */ -/*if ($j.browser.mozilla) -{ - et2_dataview_container.prototype._nodeHeight = function(_node) - { - var height = 0; - // Firefox sometimes provides fractional pixel values - we are - // forced to use those - we can obtain the fractional pixel height - // by using the window.getComputedStyle function - var compStyle = getComputedStyle(_node, null); - if (compStyle) - { - var styleHeightStr = compStyle.getPropertyValue("height"); - height = parseFloat(styleHeightStr.substr(0, - styleHeightStr.length - 2)); - - if (isNaN(height) || height < 1) - { - height = 0; - } - } - - return height; - } -} -else -{*/ - et2_dataview_container.prototype._nodeHeight = function(_node) + /** + * Returns the height of a node in pixels and zero if the element is not + * visible. The height is clamped to positive values. + * + * @param {DOMElement} _node + */ + _nodeHeight: function(_node) { return _node.offsetHeight; - }; -//} - + } +}); diff --git a/etemplate/js/et2_dataview_view_rowProvider.js b/etemplate/js/et2_dataview_view_rowProvider.js index 5c4a31ecae..5c9c0894e4 100644 --- a/etemplate/js/et2_dataview_view_rowProvider.js +++ b/etemplate/js/et2_dataview_view_rowProvider.js @@ -19,15 +19,15 @@ */ /** - * The row provider contains prototypes (full clonable dom-trees) + * The row provider contains prototypes (full clonable dom-trees) * for all registered row types. - * + * * @augments Class */ var et2_dataview_rowProvider = Class.extend( { /** - * + * * @param _outerId * @param _columnIds * @memberOf et2_dataview_rowProvider @@ -57,6 +57,10 @@ var et2_dataview_rowProvider = Class.extend( * Returns a clone of the prototype with the given name. If the generator * callback function is given, this function is called if the prototype * does not yet registered. + * + * @param {string} _name + * @param {function} _generator + * @param {object} _context */ getPrototype: function(_name, _generator, _context) { if (typeof this._prototypes[_name] == "undefined") diff --git a/etemplate/js/et2_extension_nextmatch_dynheight.js b/etemplate/js/et2_extension_nextmatch_dynheight.js index f3ac98a978..fcbb59d563 100644 --- a/etemplate/js/et2_extension_nextmatch_dynheight.js +++ b/etemplate/js/et2_extension_nextmatch_dynheight.js @@ -21,7 +21,7 @@ * Object which resizes an inner node to the maximum extend of an outer node * (without creating a scrollbar) - it achieves that by performing some very * nasty and time consuming calculations. - * + * * @augments Class */ var et2_dynheight = Class.extend( @@ -51,6 +51,9 @@ var et2_dynheight = Class.extend( /** * Resizes the inner node. When this is done, the callback function is * called. + * + * @param {function} _callback + * @param {object} _context */ update: function(_callback, _context) { // Check whether the inner node is actually visible - if not, don't @@ -103,7 +106,7 @@ var et2_dynheight = Class.extend( var h = Math.max(this.minHeight, oh + ot - it - bh - this.innerMargin - this.outerMargin); this.innerNode.height(h); - + // Update the width // Some checking to make sure it doesn't overflow the width when user // resizes the window @@ -117,7 +120,7 @@ var et2_dynheight = Class.extend( { this.innerNode.width(w); } - + // Call the callback function if (typeof _callback != "undefined") { @@ -129,6 +132,9 @@ var et2_dynheight = Class.extend( /** * Function used internally which collects all DOM-Nodes which are located * below this element. + * + * @param {DOMElement} _node + * @param {number} _bottom */ _collectBottomNodes: function(_node, _bottom) { // Calculate the bottom position of the inner node diff --git a/etemplate/js/et2_extension_nextmatch_rowProvider.js b/etemplate/js/et2_extension_nextmatch_rowProvider.js index 1789de6058..29d240ad12 100644 --- a/etemplate/js/et2_extension_nextmatch_rowProvider.js +++ b/etemplate/js/et2_extension_nextmatch_rowProvider.js @@ -19,16 +19,19 @@ */ /** - * The row provider contains prototypes (full clonable dom-trees) + * The row provider contains prototypes (full clonable dom-trees) * for all registered row types. - * + * * @augments Class */ -var et2_nextmatch_rowProvider = Class.extend( +var et2_nextmatch_rowProvider = ClassWithAttributes.extend( { /** * Creates the nextmatch row provider. - * + * + * @param {et2_nextmatch_rowProvider} _rowProvider + * @param {function} _subgridCallback + * @param {object} _context * @memberOf et2_nextmatch_rowProvider */ init: function (_rowProvider, _subgridCallback, _context) { @@ -77,7 +80,7 @@ var et2_nextmatch_rowProvider = Class.extend( // interface or do not support all attributes listed in the et2_IDetachedDOM // interface. A warning is issued for all those widgets as they heavily // degrade the performance of the dataview - var seperated = rowTemplate.seperated = + var seperated = rowTemplate.seperated = this._seperateWidgets(variableAttributes); // Remove all DOM-Nodes of all widgets inside the "remaining" slot from @@ -169,7 +172,7 @@ var et2_nextmatch_rowProvider = Class.extend( tr.appendChild(row); // Make the row expandable - if (typeof _data.content["is_parent"] !== "undefined" + if (typeof _data.content["is_parent"] !== "undefined" && _data.content["is_parent"]) { _row.makeExpandable(true, function () { @@ -189,12 +192,12 @@ var et2_nextmatch_rowProvider = Class.extend( * Placeholder for empty row * * The empty row placeholder is used when there are no results to display. - * This allows the user to still have a drop target, or use actions that + * This allows the user to still have a drop target, or use actions that * do not require a row ID, such as 'Add new'. */ _createEmptyPrototype: function() { var label = this._context && this._context.options && this._context.options.settings.placeholder; - + var placeholder = $j(document.createElement("td")) .attr("colspan",this._rowProvider.getColumnCount()) .css("height","19px") @@ -208,6 +211,8 @@ var et2_nextmatch_rowProvider = Class.extend( /** * Returns an array containing objects which have variable attributes + * + * @param {et2_widget} _widget */ _getVariableAttributeSet: function(_widget) { var variableAttributes = []; @@ -337,6 +342,8 @@ var et2_nextmatch_rowProvider = Class.extend( /** * Removes to DOM code for all widgets in the "remaining" slot + * + * @param {object} _rowTemplate */ _stripTemplateRow: function(_rowTemplate) { _rowTemplate.placeholders = []; @@ -347,7 +354,7 @@ var et2_nextmatch_rowProvider = Class.extend( // Issue a warning - widgets which do not implement et2_IDOMNode // are very slow - egw.debug("warn", "Non-clonable widget '"+ entry.widget._type + "' in dataview row - this " + + egw.debug("warn", "Non-clonable widget '"+ entry.widget._type + "' in dataview row - this " + "might be slow", entry); // Set the placeholder for the entry to null @@ -374,7 +381,7 @@ var et2_nextmatch_rowProvider = Class.extend( }, _nodeIndex: function(_node) { - if(_node.parentNode == null) + if(_node.parentNode == null) { return 0; } @@ -391,6 +398,9 @@ var et2_nextmatch_rowProvider = Class.extend( /** * Returns a function which does a relative access on the given DOM-Node + * + * @param {DOMElement} _root + * @param {DOMElement} _target */ _compileDOMAccessFunc: function(_root, _target) { function recordPath(_root, _target, _path) @@ -427,6 +437,8 @@ var et2_nextmatch_rowProvider = Class.extend( /** * Builds relative paths to the DOM-Nodes and compiles fast-access functions + * + * @param {object} _rowTemplate */ _buildNodeAccessFuncs: function(_rowTemplate) { for (var i = 0; i < _rowTemplate.seperated.detachable.length; i++) @@ -448,6 +460,10 @@ var et2_nextmatch_rowProvider = Class.extend( /** * Applies additional row data (like the class) to the tr + * + * @param {object} _data + * @param {DOMElement} _tr + * @param {object} _mgrs */ _setRowData: function (_data, _tr, _mgrs) { // TODO: Implement other fields than "class" @@ -479,7 +495,7 @@ var et2_nextmatch_rowProvider = Class.extend( // If not using category (tracker, calendar list) look for sel_options in the rows if(!categories) categories = _mgrs["sel_options"].parentMgr.getEntry(category_location); if(!categories) categories = _mgrs["sel_options"].getEntry("${row}["+category_location + "]"); - + // Cache if(categories) this.categories = categories; } @@ -525,11 +541,11 @@ var et2_nextmatch_rowProvider = Class.extend( /** * @augments et2_widget */ -var et2_nextmatch_rowWidget = et2_widget.extend(et2_IDOMNode, +var et2_nextmatch_rowWidget = et2_widget.extend(et2_IDOMNode, { /** * Constructor - * + * * @param _mgrs * @param _row * @memberOf et2_nextmatch_rowWidget @@ -549,6 +565,8 @@ var et2_nextmatch_rowWidget = et2_widget.extend(et2_IDOMNode, /** * Copies the given array manager and clones the given widgets and inserts * them into the row which has been passed in the constructor. + * + * @param {array} _widgets */ createWidgets: function(_widgets) { // Clone the given the widgets with this element as parent @@ -557,7 +575,7 @@ var et2_nextmatch_rowWidget = et2_widget.extend(et2_IDOMNode, { // Disabled columns might be missing widget - skip it if(!_widgets[i]) continue; - + this._widgets[i] = _widgets[i].clone(this); this._widgets[i].loadingFinished(); // Set column alignment from widget @@ -570,6 +588,9 @@ var et2_nextmatch_rowWidget = et2_widget.extend(et2_IDOMNode, /** * Returns the column node for the given sender + * + * @param {et2_widget} _sender + * @return {DOMElement} */ getDOMNode: function(_sender) { for (var i = 0; i < this._widgets.length; i++) @@ -588,11 +609,11 @@ var et2_nextmatch_rowWidget = et2_widget.extend(et2_IDOMNode, /** * @augments et2_widget */ -var et2_nextmatch_rowTemplateWidget = et2_widget.extend(et2_IDOMNode, +var et2_nextmatch_rowTemplateWidget = et2_widget.extend(et2_IDOMNode, { /** * Constructor - * + * * @param _root * @param _row * @memberOf et2_nextmatch_rowTemplateWidget @@ -632,6 +653,9 @@ var et2_nextmatch_rowTemplateWidget = et2_widget.extend(et2_IDOMNode, /** * Returns the column node for the given sender + * + * @param {et2_widget} _sender + * @return {DOMElement} */ getDOMNode: function(_sender) { diff --git a/etemplate/js/etemplate2.js b/etemplate/js/etemplate2.js index 6f94f7bbf2..e400a31de2 100644 --- a/etemplate/js/etemplate2.js +++ b/etemplate/js/etemplate2.js @@ -88,7 +88,10 @@ function etemplate2(_container, _menuaction) // Unique ID to prevent DOM collisions across multiple templates this.uniqueId = _container.getAttribute("id") ? _container.getAttribute("id").replace('.','-') : ''; - // Preset the object variable + /** + * Preset the object variable + * @type {et2_container} + */ this.widgetContainer = null; } diff --git a/etemplate/js/test/test_dataview.html b/etemplate/js/test/test_dataview.html index 329e424416..21b2355950 100644 --- a/etemplate/js/test/test_dataview.html +++ b/etemplate/js/test/test_dataview.html @@ -22,6 +22,7 @@ + @@ -98,7 +99,7 @@ data[i] = "uid_" + i; } - var dataprovider = Class.extend(et2_IDataProvider, { + var dataprovider = ClassWithAttributes.extend(et2_IDataProvider, { dataFetch: function (_queriedRange, _callback, _context) { var response = { diff --git a/phpgwapi/js/jsapi/app_base.js b/phpgwapi/js/jsapi/app_base.js index b1f2138d5a..50ceeef5bc 100644 --- a/phpgwapi/js/jsapi/app_base.js +++ b/phpgwapi/js/jsapi/app_base.js @@ -58,6 +58,9 @@ window.app = {classes: {}}; * // Underscore private by convention * } * }); + * + * @class AppJS + * @augments Class */ var AppJS = Class.extend( { @@ -68,11 +71,15 @@ var AppJS = Class.extend( /** * Internal reference to etemplate2 widget tree + * + * @var {et2_container} */ et2: null, /** * Internal reference to egw client-side api object for current app and window + * + * @var {egw} */ egw: null, diff --git a/phpgwapi/js/jsapi/egw_core.js b/phpgwapi/js/jsapi/egw_core.js index 1758b2e438..12b921f692 100644 --- a/phpgwapi/js/jsapi/egw_core.js +++ b/phpgwapi/js/jsapi/egw_core.js @@ -16,7 +16,7 @@ * This code setups the egw namespace and adds the "extend" function, which is * used by extension modules to inject their content into the egw object. */ -(function(_parent) { +(function() { var instanceUid = 0; @@ -46,7 +46,7 @@ { if (_cond(_arr[i])) { - _arr.splice(i, 1) + _arr.splice(i, 1); } } } @@ -173,19 +173,20 @@ /** * Creates an api instance for the given application and the given window. * - * @param _egw is the global _egw instance which should be used. - * @param _modules is the hash map which contains references to all module + * @param {globalEgw} _egw is the global _egw instance which should be used. + * @param {object} _modules is the hash map which contains references to all module * descriptors. - * @param _moduleInstances is the the object which contains the application + * @param {object} _moduleInstances is the the object which contains the application * and window specific module instances. - * @param _list is the overall instances list, to which the module should be + * @param {array} _list is the overall instances list, to which the module should be * added. - * @param _instances refers to all api instances. - * @param _app is the application for which the instance should be created. - * @param _wnd is the window for which the instance should be created. + * @param {object} _instances is the overall instances list, to which the module should be + * added. + * @param {string} _app is the application for which the instance should be created. + * @param {DOMElement} _window is the window for which the instance should be created. + * @return {egw} */ - function createEgwInstance(_egw, _modules, _moduleInstances, _list, - _instances, _app, _window) + function createEgwInstance(_egw, _modules, _moduleInstances, _list, _instances, _app, _window) { // Clone the global object var instance = cloneObject(_egw); @@ -237,18 +238,18 @@ * Returns a egw instance for the given application and the given window. If * the instance does not exist now, the instance will be created. * - * @param _egw is the global _egw instance which should be used. - * @param _modules is the hash map which contains references to all module + * @param {globalEgw} _egw is the global _egw instance which should be used. + * @param {object} _modules is the hash map which contains references to all module * descriptors. - * @param _moduleInstances is the the object which contains the application + * @param {object} _moduleInstances is the the object which contains the application * and window specific module instances. - * @param _list is the overall instances list, to which the module should be + * @param {object} _instances is the overall instances list, to which the module should be * added. - * @param _app is the application for which the instance should be created. - * @param _wnd is the window for which the instance should be created. + * @param {string} _app is the application for which the instance should be created. + * @param {DOMElement} _window is the window for which the instance should be created. + * @return {egw} */ - function getEgwInstance(_egw, _modules, _moduleInstances, _instances, _app, - _window) + function getEgwInstance(_egw, _modules, _moduleInstances, _instances, _app, _window) { // Generate the hash key for the instance descriptor object var hash = _app ? _app : '~global~'; @@ -435,6 +436,8 @@ * function and/or a window object. If you specify both, the app name * has to preceed the window object reference. If no window object is * given, the root window will be used. + * + * @return {egw} */ var egw = function() { @@ -471,7 +474,7 @@ // Generate an API instance return getEgwInstance(egw, modules, moduleInstances, instances, _app, _window); - } + }; var globalEgw = { @@ -686,9 +689,8 @@ return { 'instances': instances, 'moduleInstances': moduleInstances - } + }; } - }; // Merge the globalEgw functions into the egw object. diff --git a/phpgwapi/js/jsapi/egw_inheritance.js b/phpgwapi/js/jsapi/egw_inheritance.js index 8d216dd1d5..c75f872369 100644 --- a/phpgwapi/js/jsapi/egw_inheritance.js +++ b/phpgwapi/js/jsapi/egw_inheritance.js @@ -17,7 +17,7 @@ * ---------------------------------- * * To create a class write - * + * * MyClass = Class.extend([interfaces, ] functions); * * where "interfaces" is a single interface or an array of interfaces and @@ -28,7 +28,7 @@ * var IBreathingObject = new Interface({ * breath: function() {} * }); - * + * * var Human = Class.extend(IBreathingObject, { * walk: function() { * console.log("Walking"); @@ -37,13 +37,13 @@ * console.log(_words); * } * }); - * + * * As "Human" does not implement the function "breath", "Human" is treated as * abstract. Trying to create an instance of "Human" will throw an exception. * However - * + * * Human.prototype.implements(IBreathingObject); - * + * * will return true. Lets create a specific class of "Human": * * var ChuckNorris = Human.extend({ @@ -57,17 +57,20 @@ * }); */ -// The following code is mostly taken from +// The following code is mostly taken from // http://ejohn.org/blog/simple-javascript-inheritance/ // some parts were slightly changed for better understanding. Added possiblity // to use interfaces. -/* Simple JavaScript Inheritance +/** + * Simple JavaScript Inheritance * By John Resig http://ejohn.org/ * MIT Licensed + * + * Inspired by base2 and Prototype */ -// Inspired by base2 and Prototype -(function(){ +(function() +{ var initializing = false; /** @@ -78,11 +81,16 @@ var tracedObjects = {}; // Check whether "function decompilation" works - fnTest is normally used to - // check whether a + // check whether a var fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; - // Base "Class" for interfaces - needed to check whether an object is an - // interface + /** + * Base "Class" for interfaces - needed to check whether an object is an + * interface + * + * @param {object} fncts + * @class {Interface} + */ this.Interface = function(fncts) { for (var key in fncts) { @@ -93,6 +101,9 @@ /** * The addInterfaceFunctions function adds all interface functions the class has * to implement to the class prototype. + * + * @param {Class} prototype + * @param {array} interfaces */ function addInterfaceFunctions(prototype, interfaces) { @@ -159,24 +170,32 @@ attributes[key] = _copyMerge({}, prototype.attributes[key]); } - if(prototype._validate_attributes) - { - prototype._validate_attributes(prototype, attributes) - } - // Add the old attributes to the new ones. If the attributes already // exist, they are merged. for (var key in _super.attributes) { var _old = _super.attributes[key]; - var _new = {}; attributes[key] = _copyMerge(attributes[key], _old); } + if(prototype._validate_attributes) + { + prototype._validate_attributes(attributes); + } + prototype.attributes = attributes; }; + /** + * Create a new Class that inherits from this class. The first parameter + * is an array which defines a set of interfaces the object has to + * implement. An interface is simply an object with named functions. + * + * @param {array} interfaces + * @param {object} prop + * @return {Class} + */ function classExtend(interfaces, prop) { if (typeof prop == "undefined") @@ -243,7 +262,11 @@ // attributes addAttributeFunctions(prototype, _super); - // The dummy class constructor + /** + * The dummy class constructor + * + * @constructor {Class} + */ function Class() { // All construction is actually done in the init method if (!initializing) @@ -254,7 +277,7 @@ var func = this._ifacefuncs[i]; if (!(typeof this[func] == "function")) { - throw("Trying to create abstract object, interface " + + throw("Trying to create abstract object, interface " + "function '" + func + "' not implemented."); } } @@ -267,7 +290,7 @@ tracedObjects[this.__OBJ_UID] = { "created": new Date().getTime(), "class": className - } + }; egw.debug("log", "*" + this.__OBJ_UID + " (" + className + ")"); } @@ -284,7 +307,15 @@ // Enforce the constructor to be what we expect Class.prototype.constructor = Class; - // And make this class extendable + /** + * Create a new Class that inherits from this class. The first parameter + * is an array which defines a set of interfaces the object has to + * implement. An interface is simply an object with named functions. + * + * @param {array} interfaces + * @param {object} prop + * @return {Class} + */ Class.extend = classExtend; return Class; @@ -293,9 +324,15 @@ // The base Class implementation (does nothing) this.Class = function(){}; - // Create a new Class that inherits from this class. The first parameter - // is an array which defines a set of interfaces the object has to - // implement. An interface is simply an object with named functions. + /** + * Create a new Class that inherits from this class. The first parameter + * is an array which defines a set of interfaces the object has to + * implement. An interface is simply an object with named functions. + * + * @param {array} interfaces + * @param {object} prop + * @return {Class} + */ Class.extend = classExtend; // The base class has no attributes @@ -356,12 +393,14 @@ } return "?"; - } + }; } /** * The implements function can be used to check whether the object * implements the given interface. + * + * @param {Class} _iface interface to check */ Class.prototype.implements = function(_iface) { for (var key in _iface) @@ -378,6 +417,8 @@ * The instanceOf function can be used to check for both - classes and * interfaces. Please don't change the case of this function as this * affects IE and Opera support. + * + * @param {Class} _obj object to check */ Class.prototype.instanceOf = function(_obj) { if (_obj instanceof Interface) diff --git a/phpgwapi/js/jsapi/egw_lang.js b/phpgwapi/js/jsapi/egw_lang.js index 4d7f0afadc..e9e085a8af 100644 --- a/phpgwapi/js/jsapi/egw_lang.js +++ b/phpgwapi/js/jsapi/egw_lang.js @@ -35,8 +35,8 @@ egw.extend('lang', egw.MODULE_GLOBAL, function() { /** * Set translation for a given application * - * @param string _app - * @param object _message message => translation pairs + * @param {string} _app + * @param {object} _messages message => translation pairs * @memberOf egw */ set_lang_arr: function(_app, _messages) @@ -50,8 +50,9 @@ egw.extend('lang', egw.MODULE_GLOBAL, function() { /** * Translate a given phrase replacing optional placeholders * - * @param string _msg message to translate - * @param string _arg1 ... _argN + * @param {string} _msg message to translate + * @param {...string} _arg1 ... _argN + * @return {string} */ lang: function(_msg, _arg1) { @@ -91,10 +92,10 @@ egw.extend('lang', egw.MODULE_GLOBAL, function() { /** * Load default langfiles for an application: common, _appname, custom * - * @param _window + * @param {DOMElement} _window * @param {string} _appname name of application to load translations for * @param {function} _callback - * @param _context + * @param {object} _context */ langRequireApp: function(_window, _appname, _callback, _context) { @@ -114,17 +115,17 @@ egw.extend('lang', egw.MODULE_GLOBAL, function() { * Includes the language files for the given applications -- if those * do not already exist, include them. * - * @param _window is the window which needs the language -- this is + * @param {DOMElement} _window is the window which needs the language -- this is * needed as the "ready" event has to be postponed in that window until * all lang files are included. - * @param _apps is an array containing the applications for which the + * @param {array} _apps is an array containing the applications for which the * data is needed as objects of the following form: * { * app: , * lang: * } - * @param function _callback called after loading, if not given ready event will be postponed instead - * @param object _context for callback + * @param {function} _callback called after loading, if not given ready event will be postponed instead + * @param {object} _context for callback */ langRequire: function(_window, _apps, _callback, _context) { // Get the ready and the files module for the given window diff --git a/phpgwapi/js/jsapi/egw_links.js b/phpgwapi/js/jsapi/egw_links.js index da27200b20..e217e7236c 100644 --- a/phpgwapi/js/jsapi/egw_links.js +++ b/phpgwapi/js/jsapi/egw_links.js @@ -339,16 +339,17 @@ egw.extend('links', egw.MODULE_GLOBAL, function() { /** * Query a title of _app/_id * - * @param string _app - * @param string|int _id - * @param function _callback optinal callback, required if for responses from the server - * @param object _context context for the callback + * @param {string} _app + * @param {(string|int)} _id + * @param {function} _callback optinal callback, required if for responses from the server + * @param {object} _context context for the callback + * @param {boolean} _force_reload true load again from server, even if already cached * @return string|boolean|null string with title if it exist in local cache or null if not */ - link_title: function(_app, _id, _callback, _context) + link_title: function(_app, _id, _callback, _context, _force_reload) { // check if we have a cached title --> return it direct - if (typeof title_cache[_app] != 'undefined' && typeof title_cache[_app][_id] != 'undefined') + if (typeof title_cache[_app] != 'undefined' && typeof title_cache[_app][_id] != 'undefined' && _force_reload !== true) { if (typeof _callback == 'function') {