Issues (4868)

api/js/etemplate/widget_browser.js (2 issues)

1
/**
2
 * EGroupware  eTemplate2 widget browser
3
 * View & play with et2 widgets - javascript
4
 *
5
 * @link http://www.egroupware.org
6
 * @author Nathan Gray
7
 * @author Hadi Nategh
8
 * @copyright 2013 Nathan Gray
9
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
10
 * @package etemplate
11
 * @subpackage tools
12
 * @version $Id$
13
 */
14
15
/*egw:uses
16
	etemplate2;
17
*/
18
19
/**
20
 * widget_browser shows a list of widgets, and allows you to view them one at a time.
21
 * You can view and edit defined properties to see the effect.
22
 */
23
function widget_browser(list_div, widget_div)
24
{
25
26
	// Initialize etemplate2
27
	this.et2 = new etemplate2(widget_div, "etemplate::ajax_process_content");
28
29
	// Normally this would be passed from app
30
	var _data = {};
31
32
	// Create the basic widget container and attach it to the DOM
33
	// Not really needed, but let's be consitent with et2
34
        this.et2.widgetContainer = new et2_container(null);
35
        this.et2.widgetContainer.setApiInstance(egw('etemplate', egw.elemWindow(this.et2.DOMContainer)));
36
        this.et2.widgetContainer.setInstanceManager(this.et2);
37
        this.et2.widgetContainer.setParentDOMNode(this.et2.DOMContainer);
38
	this.et2.widgetContainer.setArrayMgrs(this.et2._createArrayManagers(_data));
39
40
	// Set up UI
41
	this.list_div = jQuery(list_div);
42
	this.widget_div = jQuery(widget_div);
43
	this.attribute_list = null;
44
45
	// Create and popuplate the widget list
46
	this._init_list();
47
48
	// Build DTD
49
	this._init_dtd();
50
}
51
52
/**
53
 * Read the widget registry and create a list.
54
 * The user can pick a widget, and we'll instanciate it.
55
 */
56
widget_browser.prototype._init_list = function()
57
{
58
	var self = this;
59
60
	// Create list
61
	var list = jQuery(document.createElement('ul'))
62
		.attr('id', 'widgets')
63
		.click(function(e) {self.select_widget(e);})
64
		.appendTo(this.list_div);
65
66
	// Sort the registry
67
	var types = [];
68
	for(var type in et2_registry)
69
	{
70
		types.push(type);
71
		}
72
	types.sort();
73
	for(var i = 0; i < types.length; i++)
74
	{
75
		list.append('<li>'+types[i]+'</li>');
76
		this.dump_attributes(types[i]);
77
	}
78
79
	// Build attribute table
80
	attribute_table = jQuery(document.createElement('table'));
81
	attribute_table.append('<thead class = "ui-widget-header"><td>'+egw().lang('Name')+"</td><td>"+egw().lang("Data type") +
82
		"</td><td>"+egw().lang("Value") + "</td></thead>");
83
	this.attribute_list = jQuery(document.createElement('tbody'))
84
		.appendTo(attribute_table);
85
86
	this.list_div.append(
87
		jQuery(document.createElement('div'))
88
			.attr('id', 'widget_attributes')
89
			.append(attribute_table)
90
	);
91
};
92
93
widget_browser.prototype.dump_attributes = function(_type)
94
{
95
	console.log(_type);
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
96
97
	try {
98
		var attrs = {};
99
		window.wb_widget = this.widget = et2_createWidget(_type, attrs, this.et2.widgetContainer);
100
		this.widget.loadingFinished();
101
102
		if(this.widget !== null && this.widget.attributes)
103
		{
104
			for(var attr in this.widget.attributes)
105
			{
106
				console.log(attr, this.widget.attributes[attr]);
107
			}
108
		}
109
	}
110
	catch(e) {
111
		console.log('*** '+_type+' error '+(typeof e.message != 'undefined' ? e.message : e));
112
	}
113
	try {
114
		if (this.widget)
115
		{
116
			this.widget.destroy();
117
			delete this.widget;
118
		}
119
	}
120
	catch(e) {
0 ignored issues
show
Coding Style Comprehensibility Best Practice introduced by
Empty catch clauses should be used with caution; consider adding a comment why this is needed.
Loading history...
121
122
	}
123
};
124
125
/**
126
 * User selected a widget from the list
127
 *
128
 * Create an instance of the widget, get its attributes, and display it.
129
 */
130
widget_browser.prototype.select_widget = function(e,f)
131
{
132
	// UI prettyness - clear selected
133
	jQuery(e.target).parent().children().removeClass("ui-state-active");
134
135
	// Clear previous widget
136
	if(this.widget)
137
	{
138
		this.et2.widgetContainer.removeChild(this.widget);
139
		this.widget.free();
140
		this.widget = null;
141
	}
142
143
	// Get the type of widget
144
	var type = jQuery(e.target).text();
145
	if(!type || e.target.nodeName != 'LI')
146
	{
147
		return;
148
	}
149
150
	// UI prettyness - show item as selected
151
	jQuery(e.target).addClass('ui-state-active');
152
153
	// Widget attributes
154
	var attrs = {};
155
156
157
	window.wb_widget = this.widget = et2_createWidget(type, attrs, this.et2.widgetContainer);
158
	this.widget.loadingFinished();
159
160
	// Attribute list
161
	this.attribute_list.empty();
162
	if(this.widget !== null && this.widget.attributes)
163
	{
164
		for(var attr in this.widget.attributes)
165
		{
166
			if(this.widget.attributes[attr].ignore) continue;
167
			this.create_attribute(attr, this.widget.attributes[attr])
168
				.appendTo(this.attribute_list);
169
						}
170
						}
171
};
172
173
174
/**
175
 * Create the UI (DOM) elements for a single widget attribute
176
 *
177
 * @param name Name of the attribute
178
 * @param settings attribute attributes (Human name, description, etc)
179
 */
180
widget_browser.prototype.create_attribute = function(name, settings)
181
{
182
	var set_function_name = "set_"+name;
183
	var row = jQuery(document.createElement("tr"))
184
		.addClass(typeof this.widget[set_function_name] == 'function' ? 'ui-state-default':'ui-state-disabled')
185
		// Human Name
186
		.append(jQuery(document.createElement('td'))
187
			.text(settings.name)
188
		)
189
		// Data type
190
		.append(jQuery(document.createElement('td'))
191
			.text(settings.type)
192
		);
193
	// Add attribute name & description as a tooltip
194
	if(settings.description)
195
	{
196
		egw().tooltipBind(row,settings.description);
197
	}
198
199
	// Value
200
	var value = jQuery(document.createElement('td')).appendTo(row);
201
	if(row.hasClass('ui-state-disabled'))
202
	{
203
		// No setter - just use text
204
		value.text(this.widget.options[name]);
205
		return row;
206
	}
207
208
	// Setter function - maybe editable?
209
	var self = this;
210
	var input = null;
211
	switch(settings.type)
212
	{
213
		case 'string':
214
			input = jQuery('<input/>')
215
				.change(function(e) {
216
					self.widget[set_function_name].apply(self.widget, [jQuery(e.target).val()]);
217
				});
218
			input.val(this.widget.options[name]);
219
			break;
220
		case 'boolean':
221
			input = jQuery('<input type="checkbox"/>')
222
				.attr("checked", this.widget.options[name])
223
				.change(function(e) {
224
					self.widget[set_function_name].apply(self.widget, [e.target.checked]);
225
				});
226
			break;
227
		default:
228
			value.text(this.widget.options[name]);
229
			return row;
230
	}
231
	input.appendTo(value);
232
233
	return row;
234
};
235
236
/**
237
 * Initialise the DTD generator
238
 */
239
widget_browser.prototype._init_dtd = function ()
240
{
241
	//Contains all widgets
242
	this.widgets = [];
243
244
	//Contains not readonly widgets
245
	this.dtd_widgets = [];
246
247
	//Contians readonly widgets
248
	this.dtd_widgets_ro = [];
249
250
	// Contains the whole DTD string
251
	this.dtd = "";
252
253
	var self = this;
254
255
	// Create DTD Generator button and bind click handler on it
256
	var dtd_btn = jQuery(document.createElement('button'))
257
			.attr({id:'dtd_btn', title:'Generates Document Type Definition (DTD) for all widgets'})
258
			.click(function(){
259
				self._dtd_builder();
260
			})
261
			.addClass('dtd_btn')
262
			.appendTo('body');
263
	dtd_btn.text('DTD Generator');
264
}
265
266
/**
267
 * Iterates over all et2_widget to build DTD tags
268
 * and display them as string
269
 *
270
 */
271
widget_browser.prototype._dtd_builder = function()
272
{
273
	var dtdContentW = "";
274
	var i = 0;
275
	for (var widget_type in et2_registry)
276
	{
277
		var attrs = {};
278
279
		// creating a dialog popups an empty dialog,
280
		// which we don't want therefore
281
		// we eliminate dialog tag from dtd ATM.
282
		if (widget_type.match(/dialog/,'i')) continue;
283
284
		if (!widget_type.match(/nextmatch/,'i'))
285
		{
286
287
			this.widgets[i] = et2_createWidget(widget_type ,attrs, this.et2.widgetContainer)
288
			if (widget_type.match(/_ro/,'i'))
289
			{
290
				this.dtd_widgets_ro.push( widget_type.replace('_ro',''));
291
			}
292
			else
293
			{
294
				this.dtd_widgets.push(widget_type);
295
				dtdContentW += this._dtd_widgets(widget_type, this.widgets[i])
296
			}
297
			i++;
298
		}
299
	}
300
	// DTD Final Content
301
	this.dtd = this._dtd_header() + dtdContentW;
302
303
	//Display DTD resault and UI to copy/download them
304
	et2_createWidget("dialog", {
305
			callback: function() {},
306
			title: egw.lang('DTD Result'),
307
			buttons:et2_dialog.BUTTONS_OK,
308
			value: {
309
				content: {
310
					value: this.dtd,
311
					message: egw.lang('DTD Content')
312
				}
313
			},
314
			template: egw.webserverUrl+'/api/templates/default/dtd.xet',
315
			modal:true,
316
			resizable:false
317
		});
318
}
319
320
/**
321
 * Builds some specific header DTD tags (e.g. ENTITY)
322
 *
323
 * @returns {String} returns dtd header tags as string
324
 */
325
widget_browser.prototype._dtd_header = function ()
326
{
327
	var dtd = '';
328
	dtd = '<!ENTITY % Widgets "' + this.dtd_widgets.join('|') + '">\r\n';
329
	dtd += '<!ELEMENT overlay (%Widgets;)*>\r\n';
330
	return dtd;
331
}
332
333
/**
334
 * Builds DTD ELEMENTS and teir ATTRLIST for given widget
335
 *
336
 * @param {string} _type widget type
337
 * @param {object} _widget widget object
338
 * @returns {String} returns generated dtd tags in string
339
 */
340
widget_browser.prototype._dtd_widgets = function (_type, _widget)
341
{
342
	var dtd = '';
343
	switch (_type)
344
	{
345
		// Special handling for menulist widget as it has a complicated structure
346
		case 'menulist':
347
			dtd = '<!ELEMENT menulist (menupopup)>\r\n';
348
			break;
349
350
		// Special handling for grid widget as it has a complicated structure
351
		case 'grid':
352
			dtd += '<!ELEMENT grid (columns,rows)>\r\n';
353
			dtd += '<!ELEMENT columns (column)*>\r\n\
354
					<!ELEMENT column EMPTY >\n\
355
					<!ATTLIST column\n\
356
						disabled CDATA #IMPLIED\n\
357
						class CDATA #IMPLIED\n\
358
						width CDATA #IMPLIED>\n\
359
					<!ELEMENT rows (row)*>\n\
360
					<!ELEMENT row (%Widgets;)>\n\
361
					<!ATTLIST row\n\
362
						class CDATA #IMPLIED\n\
363
						height CDATA #IMPLIED\n\
364
						valign CDATA #IMPLIED\n\
365
						disabled CDATA #IMPLIED\n\
366
						part CDATA #IMPLIED\n\
367
					>\r\n';
368
			break;
369
370
		// Special handling for tabbox widget as it has a complicated structure
371
		case 'tabbox':
372
			dtd += '<!ELEMENT tabbox (tabs,tabpanels)>\r\n';
373
			dtd += '<!ELEMENT tabs (tab)>\r\n';
374
			dtd += '<!ELEMENT tabpanels (template)>\r\n';
375
			break;
376
377
		// Widget which can be a parent
378
		case 'vbox':
379
		case 'hbox':
380
		case 'box':
381
		case 'groupbox':
382
		case 'template':
383
			dtd = '<!ELEMENT '+ _type + ' (%Widgets;)*>\r\n';
384
			break;
385
386
		// Other widgets which only can be used as child
387
		default:
388
			dtd = '<!ELEMENT '+ _type + ' EMPTY>\r\n';
389
	}
390
391
	dtd +='<!ATTLIST ' + _type + '\r\n';
392
	for(var attr in _widget.attributes)
393
	{
394
		//DTD attribute helper object
395
		var dtdAttrObj = {attrType:'CDATA',attrVal:'', attrReq:' #IMPLIED'};
396
397
		//if(_widget.attributes[attr].ignore) continue;
398
		switch (_widget.attributes[attr].type)
399
		{
400
			case 'boolean':
401
				dtdAttrObj.attrType = ' (true|false)';
402
				dtdAttrObj.attrVal = ' "' + _widget.attributes[attr].default + '"';
403
				dtdAttrObj.attrReq = '';
404
				break;
405
			default:
406
				dtdAttrObj.attrType = ' CDATA';
407
408
				if (_widget.attributes[attr].default !="" &&
409
						typeof _widget.attributes[attr].default != 'undefined' &&
410
						!jQuery.isEmptyObject(_widget.attributes[attr].default))
411
				{
412
					dtdAttrObj.attrReq = '';
413
					dtdAttrObj.attrVal  = ' "' + _widget.attributes[attr].default + '"';
414
				}
415
				else
416
				{
417
					dtdAttrObj.attrVal  = "";
418
				}
419
420
		}
421
		dtd += attr + dtdAttrObj.attrType +
422
				(dtdAttrObj.attrVal !=""?dtdAttrObj.attrVal:'') +
423
				dtdAttrObj.attrReq +'\r\n';
424
	}
425
	dtd += '>\r\n';
426
	return dtd;
427
}
428
429
egw_LAB.wait(function() {
430
	var wb = new widget_browser(
431
	document.getElementById("widget_list"),
432
	document.getElementById("widget_container")
433
	);
434
});
435