forked from extern/egroupware
- Styled button a little bit
- Added test for textbox - Added baseWidget and inputWidget classes - Implemented attribute system - Implemented statustext as a test for the attribute system - Ported csv_split function to JS - Implemented system for the legacy options - Added function for iterating over the widget tree
This commit is contained in:
parent
858279ad84
commit
68c7a5550e
118
etemplate/js/et2_baseWidget.js
Normal file
118
etemplate/js/et2_baseWidget.js
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/**
|
||||||
|
* eGroupWare eTemplate2 - JS Widget base class
|
||||||
|
*
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package etemplate
|
||||||
|
* @subpackage api
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @author Andreas Stöckel
|
||||||
|
* @copyright Stylite 2011
|
||||||
|
* @version $Id: et2_widget.js 36021 2011-08-07 13:43:46Z igel457 $
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*egw:uses
|
||||||
|
jquery.jquery;
|
||||||
|
lib/tooltip.js;
|
||||||
|
et2_widget;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which manages the DOM node itself. The simpleWidget class is derrived
|
||||||
|
* from et2_DOMWidget and implements the getDOMNode function. A setDOMNode
|
||||||
|
* function is provided, which attatches the given node to the DOM if possible.
|
||||||
|
*/
|
||||||
|
var et2_baseWidget = et2_DOMWidget.extend({
|
||||||
|
|
||||||
|
attributes: {
|
||||||
|
"statustext": {
|
||||||
|
"name": "Tooltip",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Tooltip which is shown for this element"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
|
this.node = null;
|
||||||
|
this.statustext = "";
|
||||||
|
|
||||||
|
this._tooltipElem = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
detatchFromDOM: function() {
|
||||||
|
// Detach this node from the tooltip node
|
||||||
|
if (this._tooltipElem)
|
||||||
|
{
|
||||||
|
egw_global_tooltip.unbindFromElement(this._tooltipElem);
|
||||||
|
this._tooltipElem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
},
|
||||||
|
|
||||||
|
attachToDOM: function() {
|
||||||
|
this._super.apply(this,arguments);
|
||||||
|
|
||||||
|
// Update the statustext
|
||||||
|
this.set_statustext(this.statustext);
|
||||||
|
},
|
||||||
|
|
||||||
|
setDOMNode: function(_node) {
|
||||||
|
if (_node != this.node)
|
||||||
|
{
|
||||||
|
// Deatch the old node from the DOM
|
||||||
|
this.detatchFromDOM();
|
||||||
|
|
||||||
|
// Set the new DOM-Node
|
||||||
|
this.node = _node;
|
||||||
|
|
||||||
|
// Attatch the DOM-Node to the tree
|
||||||
|
return this.attachToDOM();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
getDOMNode: function() {
|
||||||
|
return this.node;
|
||||||
|
},
|
||||||
|
|
||||||
|
getTooltipElement: function() {
|
||||||
|
return this.getDOMNode();
|
||||||
|
},
|
||||||
|
|
||||||
|
set_statustext: function(_value) {
|
||||||
|
// Don't execute the code below, if no tooltip will be attached/detached
|
||||||
|
if (_value == "" && !this._tooltipElem)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.statustext = _value;
|
||||||
|
|
||||||
|
//Get the domnode the tooltip should be attached to
|
||||||
|
var elem = $j(this.getTooltipElement());
|
||||||
|
|
||||||
|
if (elem)
|
||||||
|
{
|
||||||
|
//If a tooltip is already attached to the element, remove it first
|
||||||
|
if (this._tooltipElem)
|
||||||
|
{
|
||||||
|
egw_global_tooltip.unbindFromElement(this._tooltipElem);
|
||||||
|
this._tooltipElem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_value && _value != '')
|
||||||
|
{
|
||||||
|
egw_global_tooltip.bindToElement(elem, _value);
|
||||||
|
this._tooltipElem = elem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
37
etemplate/js/et2_box.js
Normal file
37
etemplate/js/et2_box.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* eGroupWare eTemplate2 - JS Box object
|
||||||
|
*
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package etemplate
|
||||||
|
* @subpackage api
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @author Andreas Stöckel
|
||||||
|
* @copyright Stylite 2011
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*egw:uses
|
||||||
|
jquery.jquery;
|
||||||
|
et2_baseWidget;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which implements the hbox and vbox tag
|
||||||
|
*/
|
||||||
|
var et2_box = et2_baseWidget.extend({
|
||||||
|
|
||||||
|
init: function(_parent, _type) {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
|
this.div = $j(document.createElement("div"))
|
||||||
|
.addClass("et2_" + _type);
|
||||||
|
|
||||||
|
this.setDOMNode(this.div[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
et2_register_widget(et2_box, ["hbox", "vbox"]);
|
||||||
|
|
@ -14,20 +14,31 @@
|
|||||||
|
|
||||||
/*egw:uses
|
/*egw:uses
|
||||||
jquery.jquery;
|
jquery.jquery;
|
||||||
et2_widget;
|
et2_baseWidget;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class which implements the "button" XET-Tag
|
* Class which implements the "button" XET-Tag
|
||||||
*/
|
*/
|
||||||
var et2_button = et2_DOMWidget.extend({
|
var et2_button = et2_baseWidget.extend({
|
||||||
|
|
||||||
|
attributes: {
|
||||||
|
"label": {
|
||||||
|
"name": "caption",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Label of the button"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
init: function(_parent) {
|
init: function(_parent) {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
|
this.label = "";
|
||||||
|
|
||||||
this.btn = $j(document.createElement("button"))
|
this.btn = $j(document.createElement("button"))
|
||||||
.addClass("et2_button");
|
.addClass("et2_button");
|
||||||
|
|
||||||
this._super.apply(this, arguments);
|
this.setDOMNode(this.btn[0]);
|
||||||
this.label = "";
|
|
||||||
},
|
},
|
||||||
|
|
||||||
set_label: function(_value) {
|
set_label: function(_value) {
|
||||||
@ -37,10 +48,6 @@ var et2_button = et2_DOMWidget.extend({
|
|||||||
|
|
||||||
this.btn.text(_value);
|
this.btn.text(_value);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
getDOMNode: function() {
|
|
||||||
return this.btn[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -10,27 +10,6 @@
|
|||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function et2_debug(_level, _msg)
|
|
||||||
{
|
|
||||||
if (typeof console != "undefined")
|
|
||||||
{
|
|
||||||
if (_level == "log" && typeof console.log == "function")
|
|
||||||
{
|
|
||||||
console.log(_msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_level == "warn" && typeof console.warn == "function")
|
|
||||||
{
|
|
||||||
console.warn(_msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_level == "error" && typeof console.error == "function")
|
|
||||||
{
|
|
||||||
console.error(_msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IE Fix for array.indexOf
|
* IE Fix for array.indexOf
|
||||||
*/
|
*/
|
||||||
@ -46,4 +25,302 @@ if (typeof Array.prototype.indexOf == "undefined")
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ET2_DEBUGLEVEL specifies which messages are printed to the console. Decrease
|
||||||
|
* the value of ET2_DEBUGLEVEL to get less messages.
|
||||||
|
*/
|
||||||
|
var ET2_DEBUGLEVEL = 0;
|
||||||
|
|
||||||
|
function et2_debug(_level, _msg)
|
||||||
|
{
|
||||||
|
if (typeof console != "undefined")
|
||||||
|
{
|
||||||
|
if (_level == "log" && ET2_DEBUGLEVEL >= 4 &&
|
||||||
|
typeof console.log == "function")
|
||||||
|
{
|
||||||
|
console.log(_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_level == "info" && ET2_DEBUGLEVEL >= 3 &&
|
||||||
|
typeof console.info == "function")
|
||||||
|
{
|
||||||
|
console.info(_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_level == "warn" && ET2_DEBUGLEVEL >= 2 &&
|
||||||
|
typeof console.warn == "function")
|
||||||
|
{
|
||||||
|
console.warn(_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_level == "error" && ET2_DEBUGLEVEL >= 1 &&
|
||||||
|
typeof console.error == "function")
|
||||||
|
{
|
||||||
|
console.error(_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array with all types supported by the et2_checkType function.
|
||||||
|
*/
|
||||||
|
var et2_validTypes = ["boolean", "string", "float", "integer", "any"];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object whith default values for the above types. Do not specify array or
|
||||||
|
* objects inside the et2_typeDefaults object, as this instance will be shared
|
||||||
|
* between all users of it.
|
||||||
|
*/
|
||||||
|
var et2_typeDefaults = {
|
||||||
|
"boolean": false,
|
||||||
|
"string": "",
|
||||||
|
"float": 0.0,
|
||||||
|
"integer": 0,
|
||||||
|
"any": null
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given value is of the given type. Strings are converted
|
||||||
|
* into the corresponding type. The (converted) value is returned. All supported
|
||||||
|
* types are listed in the et2_validTypes array.
|
||||||
|
*/
|
||||||
|
function et2_checkType(_val, _type)
|
||||||
|
{
|
||||||
|
function _err() {
|
||||||
|
throw("'" + _val + "' is not of specified _type '" + _type + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the type is "any" simply return the value again
|
||||||
|
if (_type == "any")
|
||||||
|
{
|
||||||
|
return _val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the type is boolean, check whether the given value is exactly true or
|
||||||
|
// false. Otherwise check whether the value is the string "true" or "false".
|
||||||
|
if (_type == "boolean")
|
||||||
|
{
|
||||||
|
if (_val === true || _val === false)
|
||||||
|
{
|
||||||
|
return _val;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lcv = _val.toLowerCase();
|
||||||
|
if (lcv === "true" || lcv === "false" || lcv === "")
|
||||||
|
{
|
||||||
|
return _val === "true";
|
||||||
|
}
|
||||||
|
|
||||||
|
_err();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the given value is of the type "string"
|
||||||
|
if (_type == "string")
|
||||||
|
{
|
||||||
|
if (typeof _val == "string")
|
||||||
|
{
|
||||||
|
return _val;
|
||||||
|
}
|
||||||
|
|
||||||
|
_err();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the value is already a number, otherwise try to convert it
|
||||||
|
// to one.
|
||||||
|
if (_type == "float")
|
||||||
|
{
|
||||||
|
if (typeof _val == "number")
|
||||||
|
{
|
||||||
|
return _val;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isNaN(_val))
|
||||||
|
{
|
||||||
|
return parseFloat(_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
_err();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the value is an integer by comparing the result of
|
||||||
|
// parseInt(_val) to the value itself.
|
||||||
|
if (_type == "integer")
|
||||||
|
{
|
||||||
|
if (parseInt(_val) == _val)
|
||||||
|
{
|
||||||
|
return parseInt(_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
_err();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should never come here
|
||||||
|
throw("Invalid type identifier supplied.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the given attribute with the given id. The validation checks for
|
||||||
|
* the existance of a human name, a description, a type and a default value.
|
||||||
|
* If the human name defaults to the given id, the description defaults to an
|
||||||
|
* empty string, the type defaults to any and the default to the corresponding
|
||||||
|
* type default.
|
||||||
|
*/
|
||||||
|
function et2_validateAttrib(_id, _attrib)
|
||||||
|
{
|
||||||
|
// Default ignore to false.
|
||||||
|
if (typeof _attrib["ignore"] == "undefined")
|
||||||
|
{
|
||||||
|
_attrib["ignore"] = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Break if "ignore" is set to true.
|
||||||
|
if (_attrib.ignore)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof _attrib["name"] == "undefined")
|
||||||
|
{
|
||||||
|
_attrib["name"] = _id;
|
||||||
|
et2_debug("log", "Human name ('name'-Field) for attribute '" +
|
||||||
|
_id + "' has not been supplied, set to '" + _id + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof _attrib["description"] == "undefined")
|
||||||
|
{
|
||||||
|
_attrib["description"] = "";
|
||||||
|
et2_debug("log", "Description for attribute '" +
|
||||||
|
_id + "' has not been supplied");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof _attrib["type"] == "undefined")
|
||||||
|
{
|
||||||
|
_attrib["type"] = "any";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (et2_validTypes.indexOf(_attrib["type"]) < 0)
|
||||||
|
{
|
||||||
|
et2_debug("error", "Invalid type for attribute '" + _id +
|
||||||
|
"' supplied.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the defaults
|
||||||
|
if (typeof _attrib["default"] == "undefined")
|
||||||
|
{
|
||||||
|
_attrib["default"] = et2_typeDefaults[_attrib["type"]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Equivalent to the PHP array_values function
|
||||||
|
*/
|
||||||
|
function et2_arrayValues(_arr)
|
||||||
|
{
|
||||||
|
var result = [];
|
||||||
|
for (var key in _arr)
|
||||||
|
{
|
||||||
|
if (parseInt(key) == key)
|
||||||
|
{
|
||||||
|
result.push(_arr[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Equivalent to the PHP substr function, partly take from phpjs, licensed under
|
||||||
|
* the GPL.
|
||||||
|
*/
|
||||||
|
function et2_substr (str, start, len) {
|
||||||
|
var end = str.length;
|
||||||
|
|
||||||
|
if (start < 0)
|
||||||
|
{
|
||||||
|
start += end;
|
||||||
|
}
|
||||||
|
end = typeof len === 'undefined' ? end : (len < 0 ? len + end : len + start);
|
||||||
|
|
||||||
|
return start >= str.length || start < 0 || start > end ? "" : str.slice(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split a $delimiter-separated options string, which can contain parts with
|
||||||
|
* delimiters enclosed in $enclosure. Ported from class.boetemplate.inc.php
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* - et2_csvSplit('"1,2,3",2,3') === array('1,2,3','2','3')
|
||||||
|
* - et2_csvSplit('1,2,3',2) === array('1','2,3')
|
||||||
|
* - et2_csvSplit('"1,2,3",2,3',2) === array('1,2,3','2,3')
|
||||||
|
* - et2_csvSplit('"a""b,c",d') === array('a"b,c','d') // to escape enclosures double them!
|
||||||
|
*
|
||||||
|
* @param string _str
|
||||||
|
* @param int _num=null in how many parts to split maximal, parts over this
|
||||||
|
* number end up (unseparated) in the last part
|
||||||
|
* @param string _delimiter=','
|
||||||
|
* @param string _enclosure='"'
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
function et2_csvSplit(_str, _num, _delimiter, _enclosure)
|
||||||
|
{
|
||||||
|
// Default the parameters
|
||||||
|
if (typeof _num == "undefined")
|
||||||
|
{
|
||||||
|
_num == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof _delimiter == "undefined")
|
||||||
|
{
|
||||||
|
_delimiter = ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof _enclosure == "undefined")
|
||||||
|
{
|
||||||
|
_enclosure = '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the _enclosure string does not occur in the string, simply use the
|
||||||
|
// split function
|
||||||
|
if (_str.indexOf(_enclosure) == -1)
|
||||||
|
{
|
||||||
|
return _num === null ? _str.split(_delimiter) :
|
||||||
|
_str.split(_delimiter, _num);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split the string at the delimiter and join it again, when a enclosure is
|
||||||
|
// found at the beginning/end of a part
|
||||||
|
var parts = _str.split(_delimiter);
|
||||||
|
for (var n = 0; typeof parts[n] != "undefined"; n++)
|
||||||
|
{
|
||||||
|
var part = parts[n];
|
||||||
|
|
||||||
|
if (part.charAt(0) === _enclosure)
|
||||||
|
{
|
||||||
|
var m = n;
|
||||||
|
while (typeof parts[m + 1] != "undefined" && parts[n].substr(-1) !== _enclosure)
|
||||||
|
{
|
||||||
|
parts[n] += _delimiter + parts[++m];
|
||||||
|
delete(parts[m]);
|
||||||
|
}
|
||||||
|
parts[n] = et2_substr(parts[n].replace(
|
||||||
|
new RegExp(_enclosure + _enclosure, 'g'), _enclosure), 1 , -1);
|
||||||
|
n = m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rebuild the array index
|
||||||
|
parts = et2_arrayValues(parts);
|
||||||
|
|
||||||
|
// Limit the parts to the given number
|
||||||
|
if (_num !== null && _num > 0 && _num < parts.length && parts.length > 0)
|
||||||
|
{
|
||||||
|
parts[_num - 1] = parts.slice(_num - 1, parts.length).join(_delimiter);
|
||||||
|
parts = parts.slice(0, _num);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,24 +14,82 @@
|
|||||||
|
|
||||||
/*egw:uses
|
/*egw:uses
|
||||||
jquery.jquery;
|
jquery.jquery;
|
||||||
et2_widget;
|
et2_baseWidget;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class which implements the "description" XET-Tag
|
* Class which implements the "description" XET-Tag
|
||||||
*/
|
*/
|
||||||
var et2_description = et2_DOMWidget.extend({
|
var et2_description = et2_baseWidget.extend({
|
||||||
|
|
||||||
|
attributes: {
|
||||||
|
"value": {
|
||||||
|
"name": "Caption",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Displayed text"
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options converted from the "options"-attribute.
|
||||||
|
*/
|
||||||
|
"font_style": {
|
||||||
|
"name": "Font Style",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Style may be a compositum of \"b\" and \"i\" which " +
|
||||||
|
" renders the text bold and/or italic."
|
||||||
|
},
|
||||||
|
"href": {
|
||||||
|
"name": "Link Target",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Link URL, empty if you don't wan't to display a link."
|
||||||
|
},
|
||||||
|
"activate_links": {
|
||||||
|
"name": "Replace URLs",
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "If set, URLs in the text are automatically replaced " +
|
||||||
|
"by links"
|
||||||
|
},
|
||||||
|
"label_for": {
|
||||||
|
"name": "Label for widget",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Marks the text as label for the given widget."
|
||||||
|
},
|
||||||
|
"extra_link_target": {
|
||||||
|
"name": "Link target",
|
||||||
|
"type": "string",
|
||||||
|
"default": "_self",
|
||||||
|
"description": "Link target descriptor"
|
||||||
|
},
|
||||||
|
"extra_link_popup": {
|
||||||
|
"name": "Popup",
|
||||||
|
"type": "string",
|
||||||
|
"description": "???"
|
||||||
|
},
|
||||||
|
"extra_link_title": {
|
||||||
|
"name": "Link Title",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Link title which is displayed on mouse over."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
legacyOptions: ["font_style", "href", "activate_links", "label_for",
|
||||||
|
"extra_link_target", "extra_link_popup", "extra_link_title"],
|
||||||
|
|
||||||
init: function(_parent) {
|
init: function(_parent) {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
|
this.value = "";
|
||||||
|
this.font_style = "";
|
||||||
|
|
||||||
this.span = $j(document.createElement("span"))
|
this.span = $j(document.createElement("span"))
|
||||||
.addClass("et2_label");
|
.addClass("et2_label");
|
||||||
|
|
||||||
this._super.apply(this, arguments);
|
this.setDOMNode(this.span[0]);
|
||||||
this.value = "";
|
|
||||||
},
|
},
|
||||||
|
|
||||||
set_value: function(_value) {
|
set_value: function(_value, _force) {
|
||||||
if (_value != this.value)
|
if (_value != this.value || _force)
|
||||||
{
|
{
|
||||||
this.value = _value;
|
this.value = _value;
|
||||||
|
|
||||||
@ -39,8 +97,14 @@ var et2_description = et2_DOMWidget.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getDOMNode: function() {
|
set_font_style: function(_value) {
|
||||||
return this.span[0];
|
if (_value != this.font_style)
|
||||||
|
{
|
||||||
|
this.font_style = _value;
|
||||||
|
|
||||||
|
this.span.toggleClass("et2_bold", _value.indexOf("b") >= 0);
|
||||||
|
this.span.toggleClass("et2_italic", _value.indexOf("i") >= 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -98,12 +98,6 @@ var et2_grid = et2_DOMWidget.extend({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
_readAttrWithDefault: function(_node, _name, _default) {
|
|
||||||
var val = _node.getAttribute(_name);
|
|
||||||
|
|
||||||
return (val === null) ? _default : val;
|
|
||||||
},
|
|
||||||
|
|
||||||
_getCell: function(_cells, _x, _y) {
|
_getCell: function(_cells, _x, _y) {
|
||||||
if ((0 <= _y) && (_y < _cells.length))
|
if ((0 <= _y) && (_y < _cells.length))
|
||||||
{
|
{
|
||||||
@ -132,10 +126,10 @@ var et2_grid = et2_DOMWidget.extend({
|
|||||||
var colDataEntry = this._getColDataEntry();
|
var colDataEntry = this._getColDataEntry();
|
||||||
if (nodeName == "column")
|
if (nodeName == "column")
|
||||||
{
|
{
|
||||||
colDataEntry["width"] = this._readAttrWithDefault(node, "width", "auto");
|
colDataEntry["width"] = et2_readAttrWithDefault(node, "width", "auto");
|
||||||
colDataEntry["class"] = this._readAttrWithDefault(node, "class", "");
|
colDataEntry["class"] = et2_readAttrWithDefault(node, "class", "");
|
||||||
colDataEntry["align"] = this._readAttrWithDefault(node, "align", "");
|
colDataEntry["align"] = et2_readAttrWithDefault(node, "align", "");
|
||||||
colDataEntry["span"] = this._readAttrWithDefault(node, "span", "1");
|
colDataEntry["span"] = et2_readAttrWithDefault(node, "span", "1");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -149,10 +143,10 @@ var et2_grid = et2_DOMWidget.extend({
|
|||||||
var rowDataEntry = this._getRowDataEntry();
|
var rowDataEntry = this._getRowDataEntry();
|
||||||
if (nodeName == "row")
|
if (nodeName == "row")
|
||||||
{
|
{
|
||||||
rowDataEntry["height"] = this._readAttrWithDefault(node, "height", "auto");
|
rowDataEntry["height"] = et2_readAttrWithDefault(node, "height", "auto");
|
||||||
rowDataEntry["class"] = this._readAttrWithDefault(node, "class", "");
|
rowDataEntry["class"] = et2_readAttrWithDefault(node, "class", "");
|
||||||
rowDataEntry["valign"] = this._readAttrWithDefault(node, "valign", "");
|
rowDataEntry["valign"] = et2_readAttrWithDefault(node, "valign", "");
|
||||||
rowDataEntry["span"] = this._readAttrWithDefault(node, "span", "1");
|
rowDataEntry["span"] = et2_readAttrWithDefault(node, "span", "1");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -12,6 +12,10 @@
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/*egw:uses
|
||||||
|
et2_common;
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Usage of the JS inheritance system
|
* Usage of the JS inheritance system
|
||||||
* ----------------------------------
|
* ----------------------------------
|
||||||
@ -84,10 +88,10 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The addInterfaceStuff function adds all interface functions the class has
|
* The addInterfaceFunctions function adds all interface functions the class has
|
||||||
* to implement to the class prototype.
|
* to implement to the class prototype.
|
||||||
*/
|
*/
|
||||||
function addInterfaceStuff(prototype, interfaces)
|
function addInterfaceFunctions(prototype, interfaces)
|
||||||
{
|
{
|
||||||
// Remember all interface functions in the prototype
|
// Remember all interface functions in the prototype
|
||||||
var ifaces = ((typeof prototype["_ifacefuncs"] == "undefined") ? [] :
|
var ifaces = ((typeof prototype["_ifacefuncs"] == "undefined") ? [] :
|
||||||
@ -107,7 +111,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw("Interfaces must be instanceof Interface!");
|
throw("Interfaces must be instance of Interface!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,6 +148,118 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function addAttributeFunctions(prototype, _super)
|
||||||
|
{
|
||||||
|
var 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 attrib = _super.attributes[key];
|
||||||
|
|
||||||
|
if (typeof attributes[key] == "undefined")
|
||||||
|
{
|
||||||
|
// In the case that the old attribute has no equivalent in the
|
||||||
|
// new class, simply create a reference to the old one.
|
||||||
|
attributes[key] = attrib;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Otherwise merge the two attribute descriptors.
|
||||||
|
for (var key2 in attrib)
|
||||||
|
{
|
||||||
|
if (typeof attributes[key][key2] == "undefined")
|
||||||
|
{
|
||||||
|
attributes[key][key2] = attrib[key2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the attributes
|
||||||
|
for (var key in attributes)
|
||||||
|
{
|
||||||
|
et2_validateAttrib(key, attributes[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
prototype.initAttributes = function() {
|
||||||
|
for (var key in this.attributes)
|
||||||
|
{
|
||||||
|
if (!this.attributes[key].ignore)
|
||||||
|
{
|
||||||
|
this.setAttribute(key, this.attributes[key]["default"],
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._attrsInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
prototype.setAttribute = function(_name, _value, _override) {
|
||||||
|
if (typeof this.attributes[_name] != "undefined")
|
||||||
|
{
|
||||||
|
if (!this.attributes[_name].ignore)
|
||||||
|
{
|
||||||
|
if (typeof _override == "undefined")
|
||||||
|
{
|
||||||
|
_override = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var val = et2_checkType(_value, this.attributes[_name].type);
|
||||||
|
|
||||||
|
if (typeof this["set_" + _name] == "function")
|
||||||
|
{
|
||||||
|
this["set_" + _name](val);
|
||||||
|
}
|
||||||
|
else if (_override || typeof this[_name] == "undefined")
|
||||||
|
{
|
||||||
|
this[_name] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
et2_debug("warn", "Attribute '" + _name + "' does not exist!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the given attribute. If the property does not
|
||||||
|
* exist, an error message is issued.
|
||||||
|
*/
|
||||||
|
prototype.getAttribute = function(_name) {
|
||||||
|
if (typeof this.attributes[_name] != "undefined" &&
|
||||||
|
!this.attributes[_name].ignore)
|
||||||
|
{
|
||||||
|
if (typeof this["get_" + _name] == "function")
|
||||||
|
{
|
||||||
|
return this["get_" + _name]();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return this[_name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
et2_error("error", "Attribute '" + _name + "' does not exist!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function classExtend(interfaces, prop) {
|
function classExtend(interfaces, prop) {
|
||||||
|
|
||||||
if (typeof prop == "undefined")
|
if (typeof prop == "undefined")
|
||||||
@ -158,6 +274,11 @@
|
|||||||
interfaces = [interfaces];
|
interfaces = [interfaces];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof prop.attributes == "undefined")
|
||||||
|
{
|
||||||
|
prop.attributes = {};
|
||||||
|
}
|
||||||
|
|
||||||
var _super = this.prototype;
|
var _super = this.prototype;
|
||||||
|
|
||||||
// Instantiate a base class (but only create the instance,
|
// Instantiate a base class (but only create the instance,
|
||||||
@ -199,7 +320,11 @@
|
|||||||
|
|
||||||
// Add the interface functions and the "implements" function to the
|
// Add the interface functions and the "implements" function to the
|
||||||
// prototype
|
// prototype
|
||||||
addInterfaceStuff(prototype, interfaces);
|
addInterfaceFunctions(prototype, interfaces);
|
||||||
|
|
||||||
|
// Merge the attributes and create the functions corresponding to the
|
||||||
|
// attributes
|
||||||
|
addAttributeFunctions(prototype, _super);
|
||||||
|
|
||||||
// The dummy class constructor
|
// The dummy class constructor
|
||||||
function Class() {
|
function Class() {
|
||||||
@ -221,6 +346,12 @@
|
|||||||
{
|
{
|
||||||
this.init.apply(this, arguments);
|
this.init.apply(this, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize the attributes
|
||||||
|
if (typeof this._attrsInitialized == "undefined")
|
||||||
|
{
|
||||||
|
this.initAttributes();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,5 +374,8 @@
|
|||||||
// is an array which defines a set of interfaces the object has to
|
// is an array which defines a set of interfaces the object has to
|
||||||
// implement. An interface is simply an object with named functions.
|
// implement. An interface is simply an object with named functions.
|
||||||
Class.extend = classExtend;
|
Class.extend = classExtend;
|
||||||
|
|
||||||
|
// The base class has no attributes
|
||||||
|
Class.attributes = {};
|
||||||
}).call(window);
|
}).call(window);
|
||||||
|
|
||||||
|
94
etemplate/js/et2_inputWidget.js
Normal file
94
etemplate/js/et2_inputWidget.js
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* eGroupWare eTemplate2 - JS Widget base class
|
||||||
|
*
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package etemplate
|
||||||
|
* @subpackage api
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @author Andreas Stöckel
|
||||||
|
* @copyright Stylite 2011
|
||||||
|
* @version $Id: et2_widget.js 36021 2011-08-07 13:43:46Z igel457 $
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*egw:uses
|
||||||
|
jquery.jquery;
|
||||||
|
et2_baseWidget;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for all widgets which support returning a value
|
||||||
|
*/
|
||||||
|
var et2_IInput = new Interface({
|
||||||
|
/**
|
||||||
|
* getValue has to return the value of the input widget
|
||||||
|
*/
|
||||||
|
getValue: function() {},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is dirty returns true if the value of the widget has changed since it
|
||||||
|
* was loaded.
|
||||||
|
*/
|
||||||
|
isDirty: function() {},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Causes the dirty flag to be reseted.
|
||||||
|
*/
|
||||||
|
resetDirty: function() {}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* et2_inputWidget derrives from et2_simpleWidget and implements the IInput
|
||||||
|
* interface. When derriving from this class, call setDOMNode with an input
|
||||||
|
* DOMNode.
|
||||||
|
*/
|
||||||
|
var et2_inputWidget = et2_simpleWidget.extend(et2_IInput, {
|
||||||
|
|
||||||
|
attributes: {
|
||||||
|
"value": {
|
||||||
|
"name": "Value",
|
||||||
|
"description": "The value of the widget",
|
||||||
|
"type": "string",
|
||||||
|
"default": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
|
this._oldValue = "";
|
||||||
|
},
|
||||||
|
|
||||||
|
set_value: function(_value) {
|
||||||
|
this._oldValue = _value;
|
||||||
|
|
||||||
|
if (this.node)
|
||||||
|
{
|
||||||
|
$j(this.node).val(_value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
get_value: function() {
|
||||||
|
return this.getValue();
|
||||||
|
},
|
||||||
|
|
||||||
|
getValue: function() {
|
||||||
|
if (this.node)
|
||||||
|
{
|
||||||
|
return $j(this.node).val();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._oldValue;
|
||||||
|
},
|
||||||
|
|
||||||
|
isDirty: function() {
|
||||||
|
return this._oldValue != this.getValue();
|
||||||
|
},
|
||||||
|
|
||||||
|
resetDirty: function() {
|
||||||
|
this._oldValue = this.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
178
etemplate/js/et2_tabs.js
Normal file
178
etemplate/js/et2_tabs.js
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/**
|
||||||
|
* eGroupWare eTemplate2 - JS Tabs object
|
||||||
|
*
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package etemplate
|
||||||
|
* @subpackage api
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @author Andreas Stöckel
|
||||||
|
* @copyright Stylite 2011
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*egw:uses
|
||||||
|
jquery.jquery;
|
||||||
|
et2_widget;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which implements the tabbox-tag
|
||||||
|
*/
|
||||||
|
var et2_tabbox = et2_DOMWidget.extend({
|
||||||
|
|
||||||
|
init: function(_parent, _type) {
|
||||||
|
// Create the outer tabbox container
|
||||||
|
this.container = $j(document.createElement("div"))
|
||||||
|
.addClass("et2_tabbox");
|
||||||
|
|
||||||
|
// Create the upper container for the tab flags
|
||||||
|
var cntr = $j(document.createElement("div"))
|
||||||
|
.addClass("et2_flags")
|
||||||
|
.appendTo(this.container);
|
||||||
|
|
||||||
|
this.flagContainer = $j(document.createElement("span"))
|
||||||
|
.addClass("et2_tabflagcntr")
|
||||||
|
.appendTo(cntr);
|
||||||
|
|
||||||
|
$j(document.createElement("span"))
|
||||||
|
.addClass("et2_tabspacer")
|
||||||
|
.appendTo(cntr);
|
||||||
|
|
||||||
|
// Create the lower tab container
|
||||||
|
this.tabContainer = $j(document.createElement("div"))
|
||||||
|
.addClass("et2_tabs")
|
||||||
|
.appendTo(this.container);
|
||||||
|
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
|
this.tabData = [];
|
||||||
|
},
|
||||||
|
|
||||||
|
destroy: function(_parent, _type) {
|
||||||
|
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
|
this.container = null;
|
||||||
|
this.flagContainer = null;
|
||||||
|
this.tabData = [];
|
||||||
|
},
|
||||||
|
|
||||||
|
_readTabs: function(tabData, tabs) {
|
||||||
|
et2_filteredNodeIterator(tabs, function(node, nodeName) {
|
||||||
|
if (nodeName == "tab")
|
||||||
|
{
|
||||||
|
tabData.push({
|
||||||
|
"label": et2_readAttrWithDefault(node, "label", "Tab"),
|
||||||
|
"widget": null,
|
||||||
|
"contentDiv": null,
|
||||||
|
"flagDiv": null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw("Error while parsing: Invalid tag '" + nodeName +
|
||||||
|
"' in tabs tag");
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
_readTabPanels: function(tabData, tabpanels) {
|
||||||
|
var i = 0;
|
||||||
|
et2_filteredNodeIterator(tabpanels, function(node, nodeName) {
|
||||||
|
if (i < tabData.length)
|
||||||
|
{
|
||||||
|
// Create the widget corresponding to the given node
|
||||||
|
tabData[i].widget = this.createElementFromNode(node,
|
||||||
|
nodeName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw("Error while reading tabpanels tag, too many widgets!");
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
loadFromXML: function(_node) {
|
||||||
|
// Get the tabs and tabpanels tags
|
||||||
|
var tabsElems = et2_directChildrenByTagName(_node, "tabs");
|
||||||
|
var tabpanelsElems = et2_directChildrenByTagName(_node, "tabpanels");
|
||||||
|
|
||||||
|
if (tabsElems.length == 1 && tabpanelsElems.length == 1)
|
||||||
|
{
|
||||||
|
var tabs = tabsElems[0];
|
||||||
|
var tabpanels = tabpanelsElems[0];
|
||||||
|
|
||||||
|
var tabData = [];
|
||||||
|
|
||||||
|
// Parse the "tabs" tag
|
||||||
|
this._readTabs(tabData, tabs);
|
||||||
|
|
||||||
|
// Read and create the widgets defined in the "tabpanels"
|
||||||
|
this._readTabPanels(tabData, tabpanels);
|
||||||
|
|
||||||
|
// Create the tab DOM-Nodes
|
||||||
|
this.createTabs(tabData)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw("Error while parsing tabbox, none or multiple tabs or tabpanels tags!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
createTabs: function(tabData) {
|
||||||
|
this.tabData = tabData;
|
||||||
|
|
||||||
|
this.tabContainer.empty();
|
||||||
|
this.flagContainer.empty();
|
||||||
|
|
||||||
|
for (var i = 0; i < this.tabData.length; i++)
|
||||||
|
{
|
||||||
|
// Add a spacer to the flag container
|
||||||
|
$j(document.createElement("span"))
|
||||||
|
.addClass("et2_flagspacer")
|
||||||
|
.text("-")
|
||||||
|
.appendTo(this.flagContainer);
|
||||||
|
|
||||||
|
var entry = this.tabData[i];
|
||||||
|
|
||||||
|
entry.flagDiv = $j(document.createElement("span"))
|
||||||
|
.addClass("et2_tabflag")
|
||||||
|
.text(entry.label)
|
||||||
|
.appendTo(this.flagContainer);
|
||||||
|
|
||||||
|
entry.contentDiv = $j(document.createElement("div"))
|
||||||
|
.addClass("et2_tabcntr")
|
||||||
|
.hide()
|
||||||
|
.appendTo(this.tabContainer);
|
||||||
|
|
||||||
|
// Let the widget appear on its corresponding page
|
||||||
|
entry.widget.onSetParent();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getDOMNode: function(_sender) {
|
||||||
|
if (_sender == this)
|
||||||
|
{
|
||||||
|
return this.container[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (var i = 0; i < this.tabData.length; i++)
|
||||||
|
{
|
||||||
|
if (this.tabData[i].widget == _sender)
|
||||||
|
{
|
||||||
|
return this.tabData[i].contentDiv[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
et2_register_widget(et2_tabbox, ["tabbox"]);
|
||||||
|
|
@ -26,6 +26,23 @@
|
|||||||
*/
|
*/
|
||||||
var et2_template = et2_DOMWidget.extend({
|
var et2_template = et2_DOMWidget.extend({
|
||||||
|
|
||||||
|
attributes: {
|
||||||
|
"template": {
|
||||||
|
},
|
||||||
|
"group": {
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"name": "Version",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Version of the template"
|
||||||
|
},
|
||||||
|
"lang": {
|
||||||
|
"name": "Language",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Language the template is written in"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes this template widget as a simple container.
|
* Initializes this template widget as a simple container.
|
||||||
*/
|
*/
|
||||||
@ -34,6 +51,7 @@ var et2_template = et2_DOMWidget.extend({
|
|||||||
this.isProxied = false;
|
this.isProxied = false;
|
||||||
|
|
||||||
this.div = document.createElement("div");
|
this.div = document.createElement("div");
|
||||||
|
this.id = "";
|
||||||
|
|
||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
},
|
},
|
||||||
|
@ -14,33 +14,56 @@
|
|||||||
|
|
||||||
/*egw:uses
|
/*egw:uses
|
||||||
jquery.jquery;
|
jquery.jquery;
|
||||||
et2_widget;
|
et2_inputWidget;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class which implements the "textbox" XET-Tag
|
* Class which implements the "textbox" XET-Tag
|
||||||
*/
|
*/
|
||||||
var et2_textbox = et2_DOMWidget.extend({
|
var et2_textbox = et2_baseWidget.extend({
|
||||||
|
|
||||||
init: function(_parent) {
|
attributes: {
|
||||||
this.input = $j(document.createElement("input"))
|
"multiline": {
|
||||||
.addClass("et2_input");
|
"name": "multiline",
|
||||||
|
"type": "boolean",
|
||||||
this._super.apply(this, arguments);
|
"default": false,
|
||||||
this.label = "";
|
"description": "If true, the textbox is a multiline edit field."
|
||||||
},
|
|
||||||
|
|
||||||
set_value: function(_value) {
|
|
||||||
if (_value != this.value)
|
|
||||||
{
|
|
||||||
this.label = _value;
|
|
||||||
|
|
||||||
this.input.attr("value", _value);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getDOMNode: function() {
|
init: function(_parent) {
|
||||||
return this.input[0];
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
|
this.input = null;
|
||||||
|
|
||||||
|
this.createInputWidget();
|
||||||
|
},
|
||||||
|
|
||||||
|
createInputWidget: function() {
|
||||||
|
if (this.multiline)
|
||||||
|
{
|
||||||
|
this.input = $j(document.createElement("textarea"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.input = $j(document.createElement("input"));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.input.addClass("et2_textbox");
|
||||||
|
|
||||||
|
this.setDOMNode(this.input[0]);
|
||||||
|
},
|
||||||
|
|
||||||
|
set_multiline: function(_value) {
|
||||||
|
if (_value != this.multiline)
|
||||||
|
{
|
||||||
|
this.multiline = _value;
|
||||||
|
|
||||||
|
this.createInputWidget();
|
||||||
|
|
||||||
|
// Write all settings again
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
/*egw:uses
|
/*egw:uses
|
||||||
jquery.jquery;
|
jquery.jquery;
|
||||||
|
lib/tooltip.js;
|
||||||
et2_xml;
|
et2_xml;
|
||||||
et2_common;
|
et2_common;
|
||||||
et2_inheritance;
|
et2_inheritance;
|
||||||
@ -53,6 +54,26 @@ function et2_register_widget(_constructor, _types)
|
|||||||
*/
|
*/
|
||||||
var et2_widget = Class.extend({
|
var et2_widget = Class.extend({
|
||||||
|
|
||||||
|
attributes: {
|
||||||
|
"id": {
|
||||||
|
"name": "ID",
|
||||||
|
"type": "string",
|
||||||
|
"description": "Unique identifier of the widget"
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ignore the "span" property by default - it is read by the grid and
|
||||||
|
* other widgets.
|
||||||
|
*/
|
||||||
|
"span": {
|
||||||
|
"ignore": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Set the legacyOptions array to the names of the properties the "options"
|
||||||
|
// attribute defines.
|
||||||
|
legacyOptions: [],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The init function is the constructor of the widget. When deriving new
|
* The init function is the constructor of the widget. When deriving new
|
||||||
* classes from the widget base class, always call this constructor unless
|
* classes from the widget base class, always call this constructor unless
|
||||||
@ -82,7 +103,6 @@ var et2_widget = Class.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._children = [];
|
this._children = [];
|
||||||
this.id = "";
|
|
||||||
this.type = _type;
|
this.type = _type;
|
||||||
|
|
||||||
// The supported widget classes array defines a whitelist for all widget
|
// The supported widget classes array defines a whitelist for all widget
|
||||||
@ -148,12 +168,12 @@ var et2_widget = Class.extend({
|
|||||||
_obj._children[i].clone(this, _obj._children[i].type);
|
_obj._children[i].clone(this, _obj._children[i].type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy all properties for which a setter function exists
|
// Copy all properties
|
||||||
for (var key in _obj)
|
for (var key in _obj.attributes)
|
||||||
{
|
{
|
||||||
if (key != "id" && typeof this["set_" + key] == "function")
|
if (!_obj.attributes[key].ignore && key != "id")
|
||||||
{
|
{
|
||||||
this["set_" + key](_obj[key]);
|
this.setAttribute(key, _obj.getAttribute(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -265,6 +285,31 @@ var et2_widget = Class.extend({
|
|||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function which allows iterating over the complete widget tree.
|
||||||
|
*
|
||||||
|
* @param _callback is the function which should be called for each widget
|
||||||
|
* @param _context is the context in which the function should be executed
|
||||||
|
* @param _type is an optional parameter which specifies a class/interface
|
||||||
|
* the elements have to be instanceOf.
|
||||||
|
*/
|
||||||
|
iterateOver: function(_callback, _context, _type) {
|
||||||
|
if (typeof _type == "undefined")
|
||||||
|
{
|
||||||
|
_type = et2_widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.instanceOf(_type))
|
||||||
|
{
|
||||||
|
_callback.call(_context, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < this._children.length; i++)
|
||||||
|
{
|
||||||
|
this._children[i].iterateOver(_callback, _context, _type);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
isOfSupportedWidgetClass: function(_obj)
|
isOfSupportedWidgetClass: function(_obj)
|
||||||
{
|
{
|
||||||
for (var i = 0; i < this.supportedWidgetClasses.length; i++)
|
for (var i = 0; i < this.supportedWidgetClasses.length; i++)
|
||||||
@ -336,12 +381,19 @@ var et2_widget = Class.extend({
|
|||||||
loadAttributes: function(_attrs) {
|
loadAttributes: function(_attrs) {
|
||||||
for (var i = 0; i < _attrs.length; i++)
|
for (var i = 0; i < _attrs.length; i++)
|
||||||
{
|
{
|
||||||
var attr = _attrs[i];
|
if (_attrs[i].name == "options")
|
||||||
|
|
||||||
// Check whether a setter exists for the given attribute
|
|
||||||
if (typeof this["set_" + attr.name] == "function" && attr.name.charAt(0) != "_")
|
|
||||||
{
|
{
|
||||||
this["set_" + attr.name](attr.value);
|
// Parse the legacy options
|
||||||
|
var splitted = et2_csvSplit(_attrs[i].value);
|
||||||
|
|
||||||
|
for (var i = 0; i < splitted.length && i < this.legacyOptions.length; i++)
|
||||||
|
{
|
||||||
|
this.setAttribute(this.legacyOptions[i], splitted[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.setAttribute(_attrs[i].name, _attrs[i].value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -357,13 +409,14 @@ var et2_widget = Class.extend({
|
|||||||
* update function of all child nodes.
|
* update function of all child nodes.
|
||||||
*/
|
*/
|
||||||
update: function() {
|
update: function() {
|
||||||
|
|
||||||
// Go through every property of this object and check whether a
|
// Go through every property of this object and check whether a
|
||||||
// corresponding setter function exists. If yes, it is called.
|
// corresponding setter function exists. If yes, it is called.
|
||||||
for (var key in this)
|
for (var key in this.attributes)
|
||||||
{
|
{
|
||||||
if (typeof this["set_" + key] == "function" && key.charAt(0) != "_")
|
if (!this.attributes[key].ignore && key != "id")
|
||||||
{
|
{
|
||||||
this["set_" + key](this[key]);
|
this.setAttribute(key, this.getAttribute(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,19 +425,8 @@ var et2_widget = Class.extend({
|
|||||||
{
|
{
|
||||||
this._children[i].update();
|
this._children[i].update();
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
get_id: function() {
|
|
||||||
return this.id;
|
|
||||||
},
|
|
||||||
|
|
||||||
set_id: function(_value) {
|
|
||||||
this.id = _value;
|
|
||||||
},
|
|
||||||
|
|
||||||
get_type: function() {
|
|
||||||
return this.type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -392,7 +434,13 @@ var et2_widget = Class.extend({
|
|||||||
*/
|
*/
|
||||||
var et2_IDOMNode = new Interface({
|
var et2_IDOMNode = new Interface({
|
||||||
/**
|
/**
|
||||||
* Returns the DOM-Node of the current widget.
|
* 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
|
* @param _sender The _sender parameter defines which widget is asking for
|
||||||
* the DOMNode.depending on that, the widget may return different nodes.
|
* the DOMNode.depending on that, the widget may return different nodes.
|
||||||
@ -417,19 +465,32 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, {
|
|||||||
*/
|
*/
|
||||||
init: function(_parent, _type) {
|
init: function(_parent, _type) {
|
||||||
this.parentNode = null;
|
this.parentNode = null;
|
||||||
this.visible = true;
|
|
||||||
|
this._attachSet = {
|
||||||
|
"node": null,
|
||||||
|
"parent": null
|
||||||
|
};
|
||||||
|
|
||||||
// Call the inherited constructor
|
// Call the inherited constructor
|
||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detatches the node from the DOM and clears all references to the parent
|
||||||
|
* node or the dom node of this widget.
|
||||||
|
*/
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
|
|
||||||
this.detatchFromDOM();
|
this.detatchFromDOM();
|
||||||
|
this.parentNode = null;
|
||||||
|
this._attachSet = {};
|
||||||
|
|
||||||
this._super();
|
this._super();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically tries to attach this node to the parent widget.
|
||||||
|
*/
|
||||||
onSetParent: function() {
|
onSetParent: function() {
|
||||||
// Check whether the parent implements the et2_IDOMNode interface. If
|
// Check whether the parent implements the et2_IDOMNode interface. If
|
||||||
// yes, grab the DOM node and create our own.
|
// yes, grab the DOM node and create our own.
|
||||||
@ -438,16 +499,53 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detaches the widget from the DOM tree, if it had been attached to the
|
||||||
|
* DOM-Tree using the attachToDOM method.
|
||||||
|
*/
|
||||||
detatchFromDOM: function() {
|
detatchFromDOM: function() {
|
||||||
if (this.parentNode)
|
|
||||||
|
if (this._attachSet.node && this._attachSet.parent)
|
||||||
{
|
{
|
||||||
|
// Remove the current node from the parent node
|
||||||
|
this._attachSet.parent.removeChild(this._attachSet.node);
|
||||||
|
|
||||||
|
// Reset the "attachSet"
|
||||||
|
this._attachSet = {
|
||||||
|
"node": null,
|
||||||
|
"parent": null
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches the widget to the DOM tree. Fails if the widget is already
|
||||||
|
* attached to the tree or no parent node or no node for this widget is
|
||||||
|
* defined.
|
||||||
|
*/
|
||||||
|
attachToDOM: function() {
|
||||||
|
// Attach the DOM node of this widget (if existing) to the new parent
|
||||||
var node = this.getDOMNode(this);
|
var node = this.getDOMNode(this);
|
||||||
if (node)
|
if (node && this.parentNode &&
|
||||||
|
(node != this._attachSet.node ||
|
||||||
|
this.parentNode != this._attachSet.parent))
|
||||||
{
|
{
|
||||||
this.parentNode.removeChild(node);
|
this.parentNode.appendChild(node);
|
||||||
this.parentNode = null;
|
|
||||||
}
|
// Store the currently attached nodes
|
||||||
|
this._attachSet = {
|
||||||
|
"node": node,
|
||||||
|
"parent": this.parentNode
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -462,51 +560,77 @@ var et2_DOMWidget = et2_widget.extend(et2_IDOMNode, {
|
|||||||
|
|
||||||
this.parentNode = _node;
|
this.parentNode = _node;
|
||||||
|
|
||||||
// Attach the DOM node of this widget (if existing) to the new parent
|
// And attatch the element to the DOM tree
|
||||||
var node = this.getDOMNode(this);
|
this.attachToDOM();
|
||||||
if (node && this.parentNode)
|
|
||||||
{
|
|
||||||
this.parentNode.appendChild(node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the parent node.
|
||||||
|
*/
|
||||||
getParentDOMNode: function() {
|
getParentDOMNode: function() {
|
||||||
return this.parentNode;
|
return this.parentNode;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id of the DOM-Node.
|
||||||
|
*/
|
||||||
set_id: function(_value) {
|
set_id: function(_value) {
|
||||||
this._super(_value);
|
|
||||||
|
this.id = _value;
|
||||||
|
|
||||||
var node = this.getDOMNode(this);
|
var node = this.getDOMNode(this);
|
||||||
if (node)
|
if (node)
|
||||||
|
{
|
||||||
|
if (_value != "")
|
||||||
{
|
{
|
||||||
node.setAttribute("id", _value);
|
node.setAttribute("id", _value);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node.removeAttribute("id");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Container object for not-yet supported widgets
|
* Common container object
|
||||||
*/
|
*/
|
||||||
var et2_placeholder = et2_DOMWidget.extend({
|
var et2_container = et2_simpleWidget.extend({
|
||||||
|
|
||||||
init: function() {
|
init: function() {
|
||||||
// Create the placeholder div
|
this._super.apply(this, arguments);
|
||||||
this.placeDiv = $j(document.createElement("span"))
|
|
||||||
.addClass("et2_placeholder");
|
this.setDOMNode(document.createElement("div"));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container object for not-yet supported widgets
|
||||||
|
*/
|
||||||
|
var et2_placeholder = et2_baseWidget.extend({
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
// The attrNodes object will hold the DOM nodes which represent the
|
// The attrNodes object will hold the DOM nodes which represent the
|
||||||
// values of this object
|
// values of this object
|
||||||
this.attrNodes = {};
|
this.attrNodes = {};
|
||||||
|
|
||||||
this._super.apply(this, arguments);
|
// Create the placeholder div
|
||||||
|
this.placeDiv = $j(document.createElement("span"))
|
||||||
|
.addClass("et2_placeholder");
|
||||||
|
|
||||||
var headerNode = $j(document.createElement("span"))
|
var headerNode = $j(document.createElement("span"))
|
||||||
.text(this.type)
|
.text(this.type)
|
||||||
.addClass("et2_caption");
|
.addClass("et2_caption")
|
||||||
$j(this.placeDiv).append(headerNode);
|
.appendTo(this.placeDiv);
|
||||||
|
|
||||||
|
this.setDOMNode(this.placeDiv[0]);
|
||||||
},
|
},
|
||||||
|
|
||||||
loadAttributes: function(_attrs) {
|
loadAttributes: function(_attrs) {
|
||||||
@ -523,37 +647,6 @@ var et2_placeholder = et2_DOMWidget.extend({
|
|||||||
|
|
||||||
this.attrNodes[attr.name].text(attr.name + "=" + attr.value);
|
this.attrNodes[attr.name].text(attr.name + "=" + attr.value);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
getDOMNode: function() {
|
|
||||||
return this.placeDiv[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Common container object
|
|
||||||
*/
|
|
||||||
var et2_container = et2_DOMWidget.extend({
|
|
||||||
|
|
||||||
init: function() {
|
|
||||||
this.div = document.createElement("div");
|
|
||||||
|
|
||||||
this._super.apply(this, arguments);
|
|
||||||
},
|
|
||||||
|
|
||||||
getDOMNode: function() {
|
|
||||||
return this.div;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for all widgets which support returning a value
|
|
||||||
*/
|
|
||||||
|
|
||||||
var et2_IValue = new Interface({
|
|
||||||
getValue: function() {}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,3 +114,11 @@ function et2_filteredNodeIterator(_node, _callback, _context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function et2_readAttrWithDefault(_node, _name, _default)
|
||||||
|
{
|
||||||
|
var val = _node.getAttribute(_name);
|
||||||
|
|
||||||
|
return (val === null) ? _default : val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
180
etemplate/js/lib/tooltip.js
Normal file
180
etemplate/js/lib/tooltip.js
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
/**
|
||||||
|
* eGroupware2 UI - Tooltip JS
|
||||||
|
*
|
||||||
|
* This javascript file contains the JavaScript code for the etemplate2 tooltip
|
||||||
|
*
|
||||||
|
* @link http://www.egroupware.org
|
||||||
|
* @author Andreas Stoeckel (as@stylite.de)
|
||||||
|
* @version $Id: tooltip.js 31497 2010-07-22 09:50:11Z igel457 $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Tooltip handling */
|
||||||
|
function egw_tooltip()
|
||||||
|
{
|
||||||
|
this.tooltip_div = null;
|
||||||
|
this.current_elem = null;
|
||||||
|
this.time_delta = 100;
|
||||||
|
this.show_delta = 0;
|
||||||
|
this.show_delay = 800;
|
||||||
|
this.x = 0;
|
||||||
|
this.y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
egw_tooltip.prototype.bindToElement = function(_elem, _text)
|
||||||
|
{
|
||||||
|
if (_text != '')
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
_elem.bind('mouseenter.tooltip', function(e) {
|
||||||
|
if (_elem != self.current_elem)
|
||||||
|
{
|
||||||
|
//Prepare the tooltip
|
||||||
|
self._prepare(_text);
|
||||||
|
|
||||||
|
self.current_elem = _elem;
|
||||||
|
self.show_delta = 0;
|
||||||
|
self.x = e.clientX;
|
||||||
|
self.y = e.clientY;
|
||||||
|
|
||||||
|
window.setTimeout(function() {self.showHintTimeout();}, self.time_delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
_elem.bind('mouseleave.tooltip', function() {
|
||||||
|
self.current_elem = null;
|
||||||
|
self.show_delta = 0;
|
||||||
|
//self.hide();
|
||||||
|
if (self.tooltip_div)
|
||||||
|
{
|
||||||
|
self.tooltip_div.fadeOut(100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_elem.bind('mousemove.tooltip', function(e) {
|
||||||
|
//Calculate the distance the mouse took since the last call of mousemove
|
||||||
|
var dx = self.x - e.clientX;
|
||||||
|
var dy = self.y - e.clientY;
|
||||||
|
var movedist = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
|
||||||
|
//Block appereance of the tooltip on fast movements (with small movedistances)
|
||||||
|
if (movedist > 2)
|
||||||
|
self.show_delta = 0;
|
||||||
|
|
||||||
|
self.x = e.clientX;
|
||||||
|
self.y = e.clientY;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
egw_tooltip.prototype.unbindFromElement = function(_elem)
|
||||||
|
{
|
||||||
|
_elem.unbind('mouseenter.tooltip');
|
||||||
|
_elem.unbind('mouseleave.tooltip');
|
||||||
|
_elem.unbind('mousemove.tooltip');
|
||||||
|
}
|
||||||
|
|
||||||
|
egw_tooltip.prototype.showHintTimeout = function()
|
||||||
|
{
|
||||||
|
if (this.current_elem != null)
|
||||||
|
{
|
||||||
|
this.show_delta += this.time_delta;
|
||||||
|
if (this.show_delta < this.show_delay)
|
||||||
|
{
|
||||||
|
//Repeat the call of timeout
|
||||||
|
var self = this;
|
||||||
|
window.setTimeout(function() {self.showHintTimeout();}, this.time_delta);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.show_delta = 0;
|
||||||
|
this.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
egw_tooltip.prototype._prepare = function(_text)
|
||||||
|
{
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
//Remove the old tooltip
|
||||||
|
if (this.tooltip_div)
|
||||||
|
this.hide();
|
||||||
|
|
||||||
|
//Generate the tooltip div, set it's text and append it to the body tag
|
||||||
|
this.tooltip_div = $j(document.createElement('div'));
|
||||||
|
this.tooltip_div.hide();
|
||||||
|
this.tooltip_div.append(_text);
|
||||||
|
this.tooltip_div.addClass("egw_tooltip");
|
||||||
|
$j('body').append(this.tooltip_div);
|
||||||
|
|
||||||
|
//The tooltip should automatically hide when the mouse comes over it
|
||||||
|
this.tooltip_div.mouseenter(function() {
|
||||||
|
self.hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
egw_tooltip.prototype.show = function()
|
||||||
|
{
|
||||||
|
if (this.tooltip_div)
|
||||||
|
{
|
||||||
|
//Calculate the cursor_rectangle - this is a space the tooltip might
|
||||||
|
//not overlap with
|
||||||
|
var cursor_rect = {
|
||||||
|
left: (this.x - 8),
|
||||||
|
top: (this.y - 8),
|
||||||
|
right: (this.x + 8),
|
||||||
|
bottom: (this.y + 8)
|
||||||
|
};
|
||||||
|
|
||||||
|
//Calculate how much space is left on each side of the rectangle
|
||||||
|
var window_width = $j(document).width();
|
||||||
|
var window_height = $j(document).height();
|
||||||
|
var space_left = {
|
||||||
|
left: (cursor_rect.left),
|
||||||
|
top: (cursor_rect.top),
|
||||||
|
right: (window_width - cursor_rect.right),
|
||||||
|
bottom: (window_height - cursor_rect.bottom)
|
||||||
|
};
|
||||||
|
|
||||||
|
//Get the width and the height of the tooltip
|
||||||
|
var tooltip_width = this.tooltip_div.width();
|
||||||
|
if (tooltip_width > 300) tooltip_width = 300;
|
||||||
|
var tooltip_height = this.tooltip_div.height();
|
||||||
|
|
||||||
|
|
||||||
|
if (space_left.right < tooltip_width) {
|
||||||
|
this.tooltip_div.css('left', cursor_rect.left - tooltip_width);
|
||||||
|
} else if (space_left.left >= tooltip_width) {
|
||||||
|
this.tooltip_div.css('left', cursor_rect.right);
|
||||||
|
} else {
|
||||||
|
this.tooltip_div.css('left', cursor_rect.right);
|
||||||
|
this.tooltip_div.css('max-width', space_left.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (space_left.bottom < tooltip_height) {
|
||||||
|
this.tooltip_div.css('top', cursor_rect.top - tooltip_height);
|
||||||
|
} else if (space_left.top >= tooltip_height) {
|
||||||
|
this.tooltip_div.css('top', cursor_rect.bottom);
|
||||||
|
} else {
|
||||||
|
this.tooltip_div.css('top', cursor_rect.bottom);
|
||||||
|
this.tooltip_div.css('max-height', space_left.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tooltip_div.fadeIn(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
egw_tooltip.prototype.hide = function()
|
||||||
|
{
|
||||||
|
if (this.tooltip_div)
|
||||||
|
{
|
||||||
|
this.tooltip_div.remove();
|
||||||
|
this.tooltip_div = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//A reference to the current tooltip object
|
||||||
|
window.egw_global_tooltip = new egw_tooltip();
|
||||||
|
|
8
etemplate/js/test/et2_test_description.xet
Normal file
8
etemplate/js/test/et2_test_description.xet
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<overlay>
|
||||||
|
<vbox>
|
||||||
|
<description value="This is only a test" options="bi" />
|
||||||
|
<description value="This is only a test" font_style="italic" statustext="This is only an italic label!"/>
|
||||||
|
</vbox>
|
||||||
|
</overlay>
|
||||||
|
|
@ -25,15 +25,16 @@
|
|||||||
<columns>
|
<columns>
|
||||||
<column>
|
<column>
|
||||||
<label value="Northwest"/>
|
<label value="Northwest"/>
|
||||||
<label value="Northeast"/>
|
<label value="Southwest"/>
|
||||||
</column>
|
</column>
|
||||||
<label value="Equator"/>
|
<label value="Equator"/>
|
||||||
<column>
|
<column>
|
||||||
|
<label value="Northeast"/>
|
||||||
<label value="Southwest"/>
|
<label value="Southwest"/>
|
||||||
<label value="Southeast"/>
|
|
||||||
</column>
|
</column>
|
||||||
</columns>
|
</columns>
|
||||||
|
|
||||||
|
|
||||||
<rows>
|
<rows>
|
||||||
<row/>
|
<row/>
|
||||||
<row/>
|
<row/>
|
||||||
@ -121,12 +122,12 @@
|
|||||||
<columns>
|
<columns>
|
||||||
<column>
|
<column>
|
||||||
<label value="Northwest"/>
|
<label value="Northwest"/>
|
||||||
<label value="Northeast"/>
|
<label value="Southwest"/>
|
||||||
</column>
|
</column>
|
||||||
<label value="Equator"/>
|
<label value="Equator"/>
|
||||||
<column>
|
<column>
|
||||||
|
<label value="Northeast"/>
|
||||||
<label value="Southwest"/>
|
<label value="Southwest"/>
|
||||||
<label value="Southeast"/>
|
|
||||||
</column>
|
</column>
|
||||||
</columns>
|
</columns>
|
||||||
|
|
||||||
|
18
etemplate/js/test/et2_test_tabbox.xet
Normal file
18
etemplate/js/test/et2_test_tabbox.xet
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<overlay>
|
||||||
|
<tabbox>
|
||||||
|
<tabs>
|
||||||
|
<tab label="Test1" />
|
||||||
|
<tab label="Test2" />
|
||||||
|
<tab label="Test3" />
|
||||||
|
<tab label="Test4" />
|
||||||
|
</tabs>
|
||||||
|
<tabpanels>
|
||||||
|
<label value="This is the content of tab 1"/>
|
||||||
|
<label value="This is the content of tab 2"/>
|
||||||
|
<label value="This is the content of tab 3"/>
|
||||||
|
<label value="This is the content of tab 4"/>
|
||||||
|
</tabpanels>
|
||||||
|
</tabbox>
|
||||||
|
</overlay>
|
||||||
|
|
13
etemplate/js/test/et2_test_textbox.xet
Normal file
13
etemplate/js/test/et2_test_textbox.xet
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<overlay>
|
||||||
|
<textbox value="This is a single line textbox." statustext="Write something here!"/>
|
||||||
|
<textbox multiline="true" value="This is a multi line textbox."/>
|
||||||
|
|
||||||
|
<template id="testbox">
|
||||||
|
<textbox value="This is a single line textbox." statustext="And something else here!"/>
|
||||||
|
<textbox multiline="true" value="This is a multi line textbox."/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="testbox"/>
|
||||||
|
</overlay>
|
||||||
|
|
@ -145,7 +145,7 @@
|
|||||||
</grid>
|
</grid>
|
||||||
</row>
|
</row>
|
||||||
<row class="row" disabled="@ts_viewtype">
|
<row class="row" disabled="@ts_viewtype">
|
||||||
<description value="Unitprice" options=",,ts_unitprice"/>
|
<description value="Unitprice" options=",,,ts_unitprice"/>
|
||||||
<grid>
|
<grid>
|
||||||
<columns>
|
<columns>
|
||||||
<column disabled="@pm_integration=none"/>
|
<column disabled="@pm_integration=none"/>
|
||||||
|
BIN
etemplate/js/test/gfx/gradient01.png
Normal file
BIN
etemplate/js/test/gfx/gradient01.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 249 B |
85
etemplate/js/test/gfx/gradient01.svg
Normal file
85
etemplate/js/test/gfx/gradient01.svg
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="32"
|
||||||
|
height="128"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.48.0 r9654"
|
||||||
|
sodipodi:docname="Neues Dokument 1">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3755">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0.52499998;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3757" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3759" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3755"
|
||||||
|
id="linearGradient3761"
|
||||||
|
x1="15.357142"
|
||||||
|
y1="948.78522"
|
||||||
|
x2="15.357142"
|
||||||
|
y2="1021.8951"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.979899"
|
||||||
|
inkscape:cx="88.135153"
|
||||||
|
inkscape:cy="46.311537"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1600"
|
||||||
|
inkscape:window-height="823"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="24"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Ebene 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(0,-924.36218)">
|
||||||
|
<rect
|
||||||
|
style="color:#000000;fill:url(#linearGradient3761);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.50000000000000000;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||||
|
id="rect2985"
|
||||||
|
width="32"
|
||||||
|
height="128"
|
||||||
|
x="0"
|
||||||
|
y="924.36218" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
BIN
etemplate/js/test/gfx/gradient02.png
Normal file
BIN
etemplate/js/test/gfx/gradient02.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 246 B |
90
etemplate/js/test/gfx/gradient02.svg
Normal file
90
etemplate/js/test/gfx/gradient02.svg
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="32"
|
||||||
|
height="128"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.48.0 r9654"
|
||||||
|
sodipodi:docname="gradient02.svg"
|
||||||
|
inkscape:export-filename="/home/andreas/source/egroupware/trunk/egroupware/etemplate/js/test/gfx/gradient02.png"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-ydpi="90">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3755">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0.52499998;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3757" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3759" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3755"
|
||||||
|
id="linearGradient3761"
|
||||||
|
x1="15.357142"
|
||||||
|
y1="948.78522"
|
||||||
|
x2="15.357142"
|
||||||
|
y2="1021.8951"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(-32,-1976.7244)" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.979899"
|
||||||
|
inkscape:cx="88.135153"
|
||||||
|
inkscape:cy="46.311537"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1600"
|
||||||
|
inkscape:window-height="823"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="24"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Ebene 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(0,-924.36218)">
|
||||||
|
<rect
|
||||||
|
style="color:#000000;fill:url(#linearGradient3761);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||||
|
id="rect2985"
|
||||||
|
width="32"
|
||||||
|
height="128"
|
||||||
|
x="-32"
|
||||||
|
y="-1052.3622"
|
||||||
|
transform="scale(-1,-1)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
@ -11,7 +11,10 @@
|
|||||||
<script src="../et2_description.js"></script>
|
<script src="../et2_description.js"></script>
|
||||||
<script src="../et2_grid.js"></script>
|
<script src="../et2_grid.js"></script>
|
||||||
<script src="../et2_button.js"></script>
|
<script src="../et2_button.js"></script>
|
||||||
|
<script src="../et2_box.js"></script>
|
||||||
<script src="../et2_textbox.js"></script>
|
<script src="../et2_textbox.js"></script>
|
||||||
|
<!--<script src="../et2_tabs.js"></script>-->
|
||||||
|
<script src="../lib/tooltip.js"></script>
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body {
|
body {
|
||||||
font-family: Lucida Grande, sans-serif;
|
font-family: Lucida Grande, sans-serif;
|
||||||
@ -75,6 +78,86 @@
|
|||||||
color: #101050;
|
color: #101050;
|
||||||
font-size: 10pt;
|
font-size: 10pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button.et2_button {
|
||||||
|
background-color: #E0E0E0;
|
||||||
|
background-image: url(gfx/gradient01.png);
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
|
||||||
|
border: 1px solid silver;
|
||||||
|
color: #101010;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 5px;
|
||||||
|
padding: 3px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
font-size: 9pt;
|
||||||
|
|
||||||
|
text-shadow: 1px 1px #E0E0E0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.et2_button:hover {
|
||||||
|
color: #050505;
|
||||||
|
border: 1px solid gray;
|
||||||
|
background-color: #D0D0EE;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.et2_button:active {
|
||||||
|
background-image: url(gfx/gradient02.png);
|
||||||
|
background-color: #D0D0E0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.et2_button:focus {
|
||||||
|
border: 1px solid #2c3d6f;
|
||||||
|
color: #202d52;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.et2_hbox {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et2_tabflag {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 5px;
|
||||||
|
height: 20px;
|
||||||
|
padding: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-width: 1px 1px 0 1px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: silver;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et2_tabflag.active {
|
||||||
|
border-bottom: 1px solid white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et2_textbox {
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et2_bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et2_italic {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et2_vbox div, .et2_vbox span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.egw_tooltip
|
||||||
|
{
|
||||||
|
position: fixed;
|
||||||
|
border: 1px solid #897f51;
|
||||||
|
padding: 3px;
|
||||||
|
background-color: #FDF9DB;
|
||||||
|
max-width: 300px;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -84,6 +167,9 @@
|
|||||||
<a href="#" onclick="open_xet('et2_test_timesheet_edit.xet');">Timesheet edit dialog</a>
|
<a href="#" onclick="open_xet('et2_test_timesheet_edit.xet');">Timesheet edit dialog</a>
|
||||||
<a href="#" onclick="open_xet('et2_test_template.xet');">Template proxy test</a>
|
<a href="#" onclick="open_xet('et2_test_template.xet');">Template proxy test</a>
|
||||||
<a href="#" onclick="open_xet('et2_test_grid.xet');">Grid test</a>
|
<a href="#" onclick="open_xet('et2_test_grid.xet');">Grid test</a>
|
||||||
|
<a href="#" onclick="open_xet('et2_test_tabbox.xet');">Tabs test</a>
|
||||||
|
<a href="#" onclick="open_xet('et2_test_textbox.xet');">Textbox test</a>
|
||||||
|
<a href="#" onclick="open_xet('et2_test_description.xet');">Description test</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="header">ETemplate2 container:</div>
|
<div class="header">ETemplate2 container:</div>
|
||||||
<div id="container"></div>
|
<div id="container"></div>
|
||||||
|
Loading…
Reference in New Issue
Block a user