blob: e0baaafb06e7e59b6413f9408832042fc451deb8 [file] [log] [blame]
Felix Meschberger62e1a4f2010-02-18 15:36:53 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +000017// tables container - will get hidden, when no config service available
18var configContent = false;
19
20// config table list
21var configTable = false;
22var configBody = false;
23var configRow = false;
24
25// factories table list
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +000026var factoryBody = false;
27var factoryRow = false;
Felix Meschberger62e1a4f2010-02-18 15:36:53 +000028
29
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +000030// editor dialog
31var editor = false;
Valentin Pavlov Valchev15da51b2010-03-22 09:30:38 +000032var editorMessage = false;
Felix Meschberger62e1a4f2010-02-18 15:36:53 +000033
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +000034function configure(pid, create) {
35 var uri = pluginRoot + '/' + pid;
36 $.post(create ? uri + '?create=1' : uri, null, displayConfigForm, 'json');
Felix Meschberger62e1a4f2010-02-18 15:36:53 +000037}
38
39function displayConfigForm(obj) {
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +000040 var parent = document.getElementById('editorTable');
41 clearChildren( parent )
Felix Meschberger62e1a4f2010-02-18 15:36:53 +000042
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +000043 var trEl = tr( );
Felix Meschberger62e1a4f2010-02-18 15:36:53 +000044 parent.appendChild( trEl );
45
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +000046 var tdEl = td( null, { colSpan: "2" } );
Felix Meschberger62e1a4f2010-02-18 15:36:53 +000047 trEl.appendChild( tdEl );
48
49 var formEl = createElement( "form", null, {
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +000050 id : "editorForm",
Felix Meschberger62e1a4f2010-02-18 15:36:53 +000051 method: "POST",
52 action: pluginRoot + "/" + obj.pid
53 });
54 tdEl.appendChild( formEl );
55
56 var inputEl = createElement( "input", null, {
57 type: "hidden",
58 name: "apply",
59 value: "true"
60 });
61 formEl.appendChild( inputEl );
62
63 // add the factory PID as a hidden form field if present
64 if (obj.factoryPid)
65 {
66 inputEl = createElement( "input", null, {
67 type: "hidden",
68 name: "factoryPid",
69 value: obj.factoryPid
70 });
71 formEl.appendChild( inputEl );
72 }
73
74 // add the PID filter as a hidden form field if present
75 if (obj.pidFilter)
76 {
77 inputEl = createElement( "input", null, {
78 type: "hidden",
79 name: "pidFilter",
80 value: obj.pidFilter
81 });
82 formEl.appendChild( inputEl );
83 }
84
85 inputEl = createElement( "input", null, {
86 type: "hidden",
87 name: "action",
88 value: "ajaxConfigManager"
89 });
90 formEl.appendChild( inputEl );
91
92 var tableEl = createElement( "table", null, {
93 border: 0,
94 width: "100%"
95 });
96 formEl.appendChild( tableEl );
97
98 var bodyEl = createElement( "tbody" );
99 tableEl.appendChild( bodyEl );
100
101 if (obj.description)
102 {
103 trEl = tr( );
104 tdEl = td( null, { colSpan: "2" } );
105 addText( tdEl, obj.description );
106 trEl.appendChild( tdEl );
107 bodyEl.appendChild( trEl );
108 }
109
Felix Meschberger18af5c12011-12-17 16:19:41 +0000110 if (obj.properties)
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000111 {
Felix Meschberger18af5c12011-12-17 16:19:41 +0000112 printForm(bodyEl, obj.properties);
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000113 }
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000114
115 printConfigurationInfo(parent, obj);
Valentin Pavlov Valchev15da51b2010-03-22 09:30:38 +0000116 if ( obj.service_location && obj.bundle_location && obj.service_location != obj.bundle_location) {
117 editorMessage.removeClass('ui-helper-hidden').text(i18n.err_bind.msgFormat(obj.pid, obj.bundle_location, obj.service_location));
118 } else editorMessage.addClass('ui-helper-hidden');
Valentin Pavlov Valchev178300c2010-04-15 12:33:58 +0000119
120 // ugly workaround for IE6 and IE7 - these browsers don't show correctly the dialog
121 var ua = navigator.userAgent;
122 if (ua.indexOf('MSIE 6') != -1 || ua.indexOf('MSIE 7') != -1) $(parent).html(parent.innerHTML);
123
Felix Meschberger32b3e652011-07-07 11:55:53 +0000124 initStaticWidgets(editor
125 .attr('__pid', obj.pid)
126 .attr('__location', obj.bundleLocation?obj.bundleLocation:'')
127 .dialog('option', 'title', obj.title)
128 .dialog('open'));
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000129}
130
Felix Meschberger18af5c12011-12-17 16:19:41 +0000131function printForm( /* Element */ parent, /* Object */ properties ) {
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000132 var propList;
Felix Meschberger18af5c12011-12-17 16:19:41 +0000133 for (var prop in properties)
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000134 {
Felix Meschberger18af5c12011-12-17 16:19:41 +0000135 var attr = properties[prop];
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000136
137 var trEl = tr( null, null, [
138 td( null, null, [ text( attr.name ) ] )
139 ]);
140 parent.appendChild( trEl );
141
142 var tdEl = td( null, { style: { width: "99%" } } );
143 trEl.appendChild( tdEl );
144
145 if (attr.value != undefined)
146 {
147 // check is required to also handle empty strings, 0 and false
148 tdEl.appendChild( createInput( prop, attr.value, attr.type, '99%' ) );
149 tdEl.appendChild( createElement( "br" ) );
150 }
151 else if (typeof(attr.type) == 'object')
152 {
153 // assume attr.values and multiselect
154 createMultiSelect( tdEl, prop, attr.values, attr.type, '99%' );
155 tdEl.appendChild( createElement( "br" ) );
156 }
157 else if (attr.values.length == 0)
158 {
159 tdEl.appendChild( createSpan( prop, "", attr.type ) );
160 }
161 else
162 {
163 for (var i=0;i<attr.values.length;i++)
164 {
165 tdEl.appendChild( createSpan( prop, attr.values[i], attr.type ) );
166 }
167 }
168
169 if (attr.description)
170 {
171 addText( tdEl, attr.description );
172 }
173
174 if (propList) {
175 propList += ',' + prop;
176 } else {
177 propList = prop;
178 }
179 }
180
181 parent.appendChild( createElement( "input", null, {
182 type: "hidden",
183 name: "propertylist",
184 value: propList
185 })
186 );
Felix Meschberger18af5c12011-12-17 16:19:41 +0000187
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000188 // FIX for IE6 and above: checkbox can only be checked after it is in the DOM
189 $(".checked_box").attr("checked", true).removeClass("checked_box");
190}
191
192function printConfigurationInfo( /* Element */ parent, obj )
193{
194 parent.appendChild( tr( null, null, [
195 createElement( "th", null, { colSpan: "2" }, [
196 text( i18n.cfg_title )
197 ])
198 ])
199 );
200
201 parent.appendChild( tr( null, null, [
202 td( null, null, [
203 text( i18n.pid )
204 ]),
205 td( null, null, [
206 text( obj.pid )
207 ])
208 ])
209 );
210
211 if (obj.factoryPid)
212 {
213 parent.appendChild( tr( null, null, [
214 td( null, null, [
215 text( i18n.fpid )
216 ]),
217 td( null, null, [
218 text( obj.factoryPid )
219 ])
220 ])
221 );
222 }
223
224 var binding = obj.bundleLocation;
225 if (!binding)
226 {
227 binding = i18n.unbound;
228 }
229
230 parent.appendChild( tr( null, null, [
231 td( null, null, [
232 text( i18n.binding )
233 ]),
234 td( null, null, [
235 text( binding )
236 ])
237 ])
238 );
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000239
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000240}
241
242
243var spanCounter = 0;
244/* Element */ function createSpan(prop, value, type) {
245 spanCounter++;
246 var newId = prop + spanCounter;
247
248 var addButton = createElement("input", null,
249 { type: "button",
250 style: {width : "5%"},
251 value: "+"
252 }
253 );
254 $(addButton).click(function() {addValue(prop, newId)});
255 var remButton = createElement("input", null,
256 { type: "button",
257 style: {width : "5%"},
258 value: "-"
259 }
260 );
261 $(remButton).click(function() {removeValue(newId)});
262 var spanEl = createElement( "span", null, { id: newId }, [
263 createInput( prop, value, type, '89%' ), addButton, remButton,
264 createElement("br")
265 ]);
266
267 return spanEl;
268}
269
270/* Element */ function createInput(prop, value, type, width) {
271 if (type == 11) { // AttributeDefinition.BOOLEAN
272
273 var inputEl = createElement( "input", null, {
274 type: "checkbox",
275 name: prop,
276 value: "true"
277 });
278
279 if (value && typeof(value) != "boolean")
280 {
281 value = value.toString().toLowerCase() == "true";
282 }
283 if (value)
284 {
285 $(inputEl).addClass("checked_box");
286 }
287 var hiddenEl = createElement( "input", null, {
288 type: "hidden",
289 name: prop,
290 value: "false"
291 });
292 var divEl = createElement("div");
293 divEl.appendChild(inputEl);
294 divEl.appendChild(hiddenEl);
295 return divEl;
296
297 } else if (typeof(type) == "object") { // predefined values
298
299 var selectEl = createElement( "select", null, {
300 name: prop,
301 style: { width: width }
302 });
303
304 var labels = type.labels;
305 var values = type.values;
306 for (var idx in labels) {
307 var optionEl = createElement( "option", null, {
308 value: values[idx]
309 }, [ text( labels[idx] ) ]);
310
311 if (value == values[idx])
312 {
313 optionEl.setAttribute( "selected", true );
314 }
315 selectEl.appendChild( optionEl );
316 }
317
318 return selectEl;
319
320 } else { // Simple
Felix Meschberger1568d382011-12-17 15:26:02 +0000321 // Metatype 1.2: Attr type 12 is PASSWORD
322 var elType = (type == 12) ? "password" : "text";
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000323 return createElement( "input", null, {
Felix Meschberger1568d382011-12-17 15:26:02 +0000324 type: elType,
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000325 name: prop,
326 value: value,
327 style: { width: width }
328 });
329 }
330}
331
332function createMultiSelect(/* Element */ parent, prop, values, options, width) {
333 // convert value list into 'set'
334 var valueSet = new Object();
335 for (var idx in values) {
336 valueSet[ values[idx] ] = true;
337 }
338
339 var labels = options.labels;
340 var values = options.values;
341 for (var idx in labels) {
342
343 var inputEl = createElement( "input", null, {
344 type: "checkbox",
345 name: prop,
346 value: values[idx]
347 });
348
349 if (valueSet[ values[idx] ])
350 {
351 inputEl.setAttribute( "checked", true );
352 }
353
354 var labelEl = createElement( "label", "multiselect" );
355 labelEl.appendChild( inputEl );
356 addText( labelEl, labels[idx] );
357
358 parent.appendChild( labelEl );
359 }
360}
361
362
363function addValue(prop, vidx)
364{
365 var span = document.getElementById(vidx);
366 if (!span)
367 {
368 return;
369 }
370 var newSpan = createSpan(prop, '');
371 span.parentNode.insertBefore(newSpan, span.nextSibling);
372 // FIX for IE6 and above: checkbox can only be checked after it is in the DOM
373 $(".checked_box").attr("checked", true).removeClass("checked_box");
374 //$(span).ready(initStaticWidgets);
375}
376
377function removeValue(vidx)
378{
379 var span = document.getElementById(vidx);
380 if (!span)
381 {
382 return;
383 }
384 span.parentNode.removeChild(span);
385}
386
387function configConfirm(/* String */ message, /* String */ title, /* String */ location)
388{
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000389 if (title) {
390 message += "\r\n" + i18n.del_config + title;
391 }
392 if (location) {
393 message += "\r\n" + i18n.del_bundle + location;
394 }
395
396 return confirm(message);
397}
398
Felix Meschberger32b3e652011-07-07 11:55:53 +0000399function deleteConfig(/* String */ configId, /* String */ bundleLocation)
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000400{
Felix Meschberger32b3e652011-07-07 11:55:53 +0000401 if ( configConfirm(i18n.del_ask, configId, bundleLocation) ) {
402 $.post(pluginRoot + '/' + configId + '?apply=1&delete=1', null, function() {
403 document.location.href = pluginRoot;
404 }, 'json');
405 return true;
406 }
407 return false;
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000408}
409
Felix Meschberger32b3e652011-07-07 11:55:53 +0000410function unbindConfig(/* String */ configId, /* String */ bundleLocation)
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000411{
Felix Meschberger32b3e652011-07-07 11:55:53 +0000412 if ( configConfirm(i18n.unbind_ask, configId, bundleLocation) ) {
413 $.post(pluginRoot + '/' + configId + '?unbind=1', null, function() {
414 document.location.href = pluginRoot + '/' + configId;
415 }, 'json');
416 return true;
417 }
418 return false;
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000419}
420
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000421function addConfig(conf) {
422 var tr = configRow.clone().appendTo(configBody);
Felix Meschbergerfdfbd602010-03-17 06:55:00 +0000423
424 // rendering name - indented if factory pid is set
Valentin Pavlov Valchev178300c2010-04-15 12:33:58 +0000425 var nms = tr.find('td:eq(0) div');
Felix Meschbergerfdfbd602010-03-17 06:55:00 +0000426 if (conf.fpid) {
427 nms.after(conf.id);
428 tr.attr('fpid', conf.name);
429 } else {
430 nms.addClass('ui-helper-hidden').parent().text(conf.name);
431 }
432
433 tr.find('td:eq(0)').click(function() { // name & edit
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000434 configure(conf.id);
435 });
Felix Meschbergerfdfbd602010-03-17 06:55:00 +0000436 tr.find('td:eq(1)').html(conf.bundle ? '<a href="' + pluginRoot + '/../bundles/' + conf.bundle + '">' + conf.bundle_name + '</a>' : '-'); // binding
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000437
438 // buttons
439 tr.find('li:eq(0)').click(function() { // edit
440 configure(conf.id);
441 });
442 tr.find('li:eq(2)').click(function() { // delete
Felix Meschberger32b3e652011-07-07 11:55:53 +0000443 deleteConfig(conf.id, conf.bundle_name);
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000444 });
Felix Meschberger32b3e652011-07-07 11:55:53 +0000445 if (conf.bundle) {
446 tr.find('li:eq(1)').click(function() { // unbind
447 unbindConfig(conf.id, conf.bundle_name);
448 }).removeClass('ui-state-disabled');
449 }
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000450}
451
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000452function addFactoryConfig(conf) {
Felix Meschbergerfdfbd602010-03-17 06:55:00 +0000453 var tr = factoryRow.clone().appendTo(configTable).attr('fpid', conf.name);
454 //tr.find('td:eq(1)').text(conf.id); // fpid
Felix Meschberger1206e2c2010-03-13 15:09:51 +0000455 tr.find('td:eq(0)').text(conf.name).click(function() { // name & edit
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000456 configure(conf.id, true);
457 });
458 // buttons
459 tr.find('li:eq(0)').click(function() { // edit
460 configure(conf.id, true);
461 });
462}
463
Felix Meschbergerfdfbd602010-03-17 06:55:00 +0000464function treetableExtraction(node) {
465 var td = $(node);
466 var text = td.text();
467 if (!text) return text;
468
469 // current sort order
470 var desc = $(this)[0].sortList[0][1];
471
472 var row = td.parent();
473 var fpid = row.attr('fpid');
474
475 // factory row
476 if ( row.hasClass('fpid') && fpid) return fpid + (desc==0?1:0) + text;
477
478 // bundle or name row
479 if ( fpid ) return fpid + desc + text;
480
481 return mixedLinksExtraction(node);
482};
483
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000484$(document).ready(function() {
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000485 configContent = $('#configContent');
486 // config table list
Felix Meschbergerfdfbd602010-03-17 06:55:00 +0000487 configTable = $('#configTable');
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000488 configBody = configTable.find('tbody');
Felix Meschbergerfdfbd602010-03-17 06:55:00 +0000489 configRow = configBody.find('tr:eq(0)').clone();
490 factoryRow = configBody.find('tr:eq(1)').clone();
Felix Meschberger1206e2c2010-03-13 15:09:51 +0000491
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000492 // setup button - cannot inline in dialog option because of i18n
493 var _buttons = {};
494 _buttons[i18n.abort] = function() {
495 $(this).dialog('close');
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000496 }
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000497 _buttons[i18n.reset] = function() {
498 var form = document.getElementById('editorForm');
499 if (form) form.reset();
500 }
Felix Meschberger32b3e652011-07-07 11:55:53 +0000501 _buttons[i18n.del] = function() {
502 if (deleteConfig($(this).attr('__pid'), $(this).attr('__location'))) {
503 $(this).dialog('close');
504 }
505 }
506 _buttons[i18n.unbind_btn] = function() {
507 unbindConfig($(this).attr('__pid'), $(this).attr('__location'));
508 }
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000509 _buttons[i18n.save] = function() {
Valentin Pavlov Valchevd5900c02011-09-15 07:06:36 +0000510 $.post(pluginRoot + '/' + $(this).attr('__pid') + '?' + $(this).find('form').serialize(), function() {
511 // reload on success - prevents AJAX errors - see FELIX-3116
512 document.location.href = pluginRoot;
513 });
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000514 $(this).dialog('close');
515 }
516 // prepare editor, but don't open yet!
517 editor = $('#editor').dialog({
518 autoOpen : false,
519 modal : true,
520 width : '90%',
521 closeText: i18n.abort,
522 buttons : _buttons
523 });
Valentin Pavlov Valchev15da51b2010-03-22 09:30:38 +0000524 editorMessage = editor.find('p');
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000525
526 // display the configuration data
527 $(".statline").html(configData.status ? i18n.stat_ok : i18n.stat_missing);
528 if (configData.status) {
Felix Meschbergerfdfbd602010-03-17 06:55:00 +0000529 configBody.empty();
530 var factories = {};
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000531
Felix Meschbergerfdfbd602010-03-17 06:55:00 +0000532 for(var i in configData.pids) {
533 var c = configData.pids[i];
534 if (c.fpid) {
535 if (!factories[c.fpid]) factories[c.fpid] = new Array();
536 factories[c.fpid].push(c);
537 } else {
538 addConfig(c);
539 }
540 }
541 for(var i in configData.fpids) {
542 addFactoryConfig(configData.fpids[i]);
Felix Meschberger1206e2c2010-03-13 15:09:51 +0000543
Felix Meschbergerc73f5772011-12-19 12:54:03 +0000544 var fpid = configData.fpids[i].id;
545 var confs = factories[ fpid ];
546 if (confs) {
547 for (var j in confs) {
548 addConfig(confs[j]);
549 }
550 delete factories[ fpid ];
Felix Meschbergerfdfbd602010-03-17 06:55:00 +0000551 }
552 }
Felix Meschbergerc73f5772011-12-19 12:54:03 +0000553 for(var fpid in factories) {
554 var flist = factories[fpid];
555 for(var i in flist) {
556 delete flist[i].fpid; // render as regular config
557 addConfig(flist[i]);
558 }
559 }
Felix Meschbergerfdfbd602010-03-17 06:55:00 +0000560 initStaticWidgets(configTable);
561
562 // init tablesorte
563 configTable.tablesorter({
564 headers: { 2: { sorter: false } },
565 sortList: [[0,1]],
566 textExtraction: treetableExtraction
567 }).bind('sortStart', function() { // clear cache, otherwse extraction will not work
568 var table = $(this).trigger('update');
569 }).find('th:eq(0)').click();
Carsten Ziegeler4e070fe2010-03-10 16:41:53 +0000570 } else {
571 configContent.addClass('ui-helper-hidden');
572 }
573 if (selectedPid) configure(selectedPid);
Felix Meschberger62e1a4f2010-02-18 15:36:53 +0000574});