Partial fix for FELIX-2286 /Various rendering issues with IE/
https://issues.apache.org/jira/browse/FELIX-2286

fixes component and services plugins

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@934380 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentsServlet.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentsServlet.java
index 2b4f6b0..1783911 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentsServlet.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/compendium/ComponentsServlet.java
@@ -68,7 +68,7 @@
     private static final String OPERATION = "action";
     private static final String OPERATION_ENABLE = "enable";
     private static final String OPERATION_DISABLE = "disable";
-    private static final String OPERATION_CONFIGURE = "configure";
+    //private static final String OPERATION_CONFIGURE = "configure";
 
     // needed services
     private static final String SCR_SERVICE = ScrService.class.getName();
@@ -249,35 +249,23 @@
         jw.value( name );
         jw.key( "state" );
         jw.value( ComponentConfigurationPrinter.toStateString( state ) );
+        jw.key( "stateRaw" );
+        jw.value( state );
+        
+        final Dictionary props = component.getProperties();
 
-        final String pid = ( String ) component.getProperties().get( Constants.SERVICE_PID );
+        final String pid = (String) (props != null ?  props.get( Constants.SERVICE_PID ) : null);
         if ( pid != null )
         {
             jw.key("pid");
             jw.value(pid);
-        }
-        // component actions
-        jw.key( "actions" );
-        jw.array();
-
-        if ( state == Component.STATE_DISABLED )
-        {
-            action(jw, true, OPERATION_ENABLE, "Enable", "enable" );
-        }
-        if ( state != Component.STATE_DISABLED && state != Component.STATE_DESTROYED )
-        {
-            action(jw, true, OPERATION_DISABLE, "Disable", "disable" );
-        }
-        if ( pid != null )
-        {
-            if ( isConfigurable( component.getBundle(), pid ) )
+            if ( isConfigurable( component.getBundle(), pid ) ) 
             {
-                action(jw, true, OPERATION_CONFIGURE, "Configure", "configure" );
+                jw.key("configurable");
+                jw.value(pid);
             }
         }
 
-        jw.endArray();
-
         // component details
         if ( details )
         {
@@ -287,15 +275,6 @@
         jw.endObject();
     }
 
-    private void action( JSONWriter jw, boolean enabled, String op, String opLabel, String image ) throws JSONException
-    {
-        jw.object();
-        jw.key( "enabled" ).value( enabled );
-        jw.key( "name" ).value( opLabel );
-        jw.key( "link" ).value( op );
-        jw.key( "image" ).value( image );
-        jw.endObject();
-    }
 
     private void gatherComponentDetails( JSONWriter jw, Component component ) throws JSONException
     {
diff --git a/webconsole/src/main/resources/res/ui/components.js b/webconsole/src/main/resources/res/ui/components.js
index 9b2ba33..b0d084c 100644
--- a/webconsole/src/main/resources/res/ui/components.js
+++ b/webconsole/src/main/resources/res/ui/components.js
@@ -28,7 +28,7 @@
 			$(".statline").html(i18n.stat_ok.msgFormat(eventData.status));
 			$('#scr').removeClass('ui-helper-hidden');
 			
-			$("#plugin_table > tbody > tr").remove();
+			tableBody.empty();
 			for ( var idx in eventData.data ) {
 				entry( eventData.data[idx] );
 			}
@@ -39,75 +39,27 @@
 }
 
 function entry( /* Object */ dataEntry ) {
-	var trElement = tr( null, { id: "entry" + dataEntry.id } );
-	entryInternal( trElement,  dataEntry );
-	$("#plugin_table > tbody").append(trElement);	
-}
-
-function actionButton( /* Element */ parent, /* string */ id, /* Obj */ action, /* string */ pid ) {
-	var enabled = action.enabled;
-	var op = action.link;
-	var opLabel = action.name;
-	var img = action.image;
-	// fixup JQuery UI icons
-	if (img == 'configure')	  { img = 'wrench'
-	} else if (img == 'disable') { img = 'stop' //locked
-	} else if (img == 'enable')  { img = 'play' //unlocked
-	}
-	
-	// apply i18n
-	opLabel = i18n[opLabel] ? i18n[opLabel] : opLabel;
-	
-	var arg = id;
-	if ( op == "configure" ) {
-		arg = pid
-	}
-	var input = createElement('li', 'dynhover', {
-		title: opLabel
-	});
-	$(input)
-		.html('<span class="ui-icon ui-icon-'+img+'"></span>')
-		.click(function() {changeDataEntryState(arg, op)});
-
-	if (!enabled) {
-		$(input).attr('disabled', true).addClass('ui-state-disabled');
-		
-	}
-	parent.appendChild( input );
-}
-
-function entryInternal( /* Element */ parent, /* Object */ dataEntry ) {
 	var id = dataEntry.id;
 	var name = dataEntry.name;
-	var state = dataEntry.state;
 
-	var inputElement = createElement('span', 'ui-icon ui-icon-triangle-1-e', {
-		title: "Details",
-		id: 'img' + id,
-		style: {display: "inline-block"}
-	});
-	$(inputElement).click(function() {showDetails(id)});
-	var titleElement;
-	if ( drawDetails ) {
-		titleElement = text(name);
+	var _ = tableEntryTemplate.clone().appendTo(tableBody).attr('id', 'entry' + dataEntry.id);
+
+	_.find('.bIcon').attr('id', 'img' + id).click(function() {
+		showDetails(id);
+	}).after(drawDetails ? name : ('<a href="' + window.location.pathname + '/' + id + '">' + name + '</a>'));
+
+	_.find('td:eq(0)').text( id );
+	_.find('td:eq(2)').text( dataEntry.state );
+
+	// setup buttons
+	if ( dataEntry.stateRaw == 1 || dataEntry.stateRaw == 1024 ) { // disabled or disabling
+		_.find('li:eq(0)').removeClass('ui-helper-hidden').click(function() { changeDataEntryState(id, 'enable') });
 	} else {
-		titleElement = createElement ("a", null, {
-			href: window.location.pathname + "/" + id
-		});
-		titleElement.appendChild(text(name));
+		_.find('li:eq(1)').removeClass('ui-helper-hidden').click(function() { changeDataEntryState(id, 'disable') });
 	}
-
-	parent.appendChild( td( null, null, [ text( id ) ] ) );
-	parent.appendChild( td( null, null, [ inputElement, text(" "), titleElement ] ) );
-	parent.appendChild( td( null, null, [ text( state ) ] ) );
-	var actionsTd = td( null, null );
-	var div = createElement('ul', 'icons ui-widget');
-	actionsTd.appendChild(div);
-
-	for ( var a in dataEntry.actions ) {
-		actionButton( div, id, dataEntry.actions[a], dataEntry.pid );
-	}
-	parent.appendChild( actionsTd );
+	if ( dataEntry.configurable ) _.find('li:eq(2)').removeClass('ui-helper-hidden').click(function() { // configure
+		changeDataEntryState(dataEntry.pid, 'configure');
+	});	
 }
 
 function changeDataEntryState(/* long */ id, /* String */ action) {
@@ -199,9 +151,14 @@
 	}
 }
 
+var tableBody = false;
+var tableEntryTemplate = false;
 
 $(document).ready(function(){
-	renderData (scrData);
+	tableBody = $('#plugin_table tbody');
+	tableEntryTemplate = tableBody.find('tr').clone();
+
+	renderData(scrData);
 
 	$(".reloadButton").click(loadData);
 
diff --git a/webconsole/src/main/resources/res/ui/services.js b/webconsole/src/main/resources/res/ui/services.js
index 2dfbf07..531c600 100644
--- a/webconsole/src/main/resources/res/ui/services.js
+++ b/webconsole/src/main/resources/res/ui/services.js
@@ -14,6 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+var tableEntryTemplate = false;
+var tableBody = false;
 
 function renderData(eventData) {
 	$('.statline').empty().append(i18n.statline.msgFormat(eventData.serviceCount));
@@ -21,52 +23,22 @@
 	for ( var idx in eventData.data) {
 		entry(eventData.data[idx]);
 	}
-	$('#plugin_table').trigger('update');
 	if (drawDetails) {
 		renderDetails(eventData);
 	}
 }
 
 function entry( /* Object */dataEntry) {
-	var trElement = tr(null, {
-		id : 'entry' + dataEntry.id
-	});
-	entryInternal(trElement, dataEntry);
-	$('#plugin_table > tbody').append(trElement);
-}
-
-function entryInternal( /* Element */parent, /* Object */dataEntry) {
 	var id = dataEntry.id;
 	var name = dataEntry.id;
 
-	// right arrow
-	var inputElement = createElement('span', 'ui-icon ui-icon-triangle-1-e', {
-		title: i18n.detailsTip,
-		id: 'img' + id,
-		style: {display: 'inline-block'}
-	});
-
-	$(inputElement).click(function() {
-		showDetails(id)
-	});
-	var titleElement;
-	if (drawDetails) {
-		titleElement = text(name);
-	} else {
-		titleElement = createElement('a', null, {
-			href : window.location.pathname + '/' + id
-		});
-		titleElement.appendChild(text(name));
-	}
-	var bundleElement = createElement('a', null, {
-		href : bundlePath + dataEntry.bundleId
-	});
-	bundleElement.appendChild(text(dataEntry.bundleSymbolicName + ' ('
-			+ dataEntry.bundleId + ')'));
-
-	parent.appendChild(td(null, null, [ inputElement, text(' '), titleElement ]));
-	parent.appendChild(td(null, null, [ text(dataEntry.types) ]));
-	parent.appendChild(td(null, null, [ bundleElement ]));
+	var _ = tableEntryTemplate.clone().attr('id', 'entry' + id).appendTo(tableBody);
+	_.find('.bIcon').attr('id', 'img' + id).click(function() {
+		showDetails(id);
+	}).after(drawDetails ? name : ('<a href="' + window.location.pathname + '/' + id + '">' + name + '</a>'));
+	  
+	_.find('td:eq(1)').text(dataEntry.types);
+	_.find('td:eq(2)').html('<a href="' + bundlePath + dataEntry.bundleId + '">' + dataEntry.bundleSymbolicName + ' (' + dataEntry.bundleId + ')</a>' );
 }
 
 function showDetails(id) {
@@ -174,17 +146,19 @@
 	return txt;
 }
 
-function renderServices(data) {
-	$(document).ready(function() {
-		renderData(data);
 
-		$('#plugin_table').tablesorter( {
-			headers : {
-				0 : { sorter : 'digit' }
-			},
-			sortList : [ [ 1, 0 ] ],
-			textExtraction : mixedLinksExtraction,
-			widgets: ['zebra']
-		});
+$(document).ready(function() {
+	tableBody = $('#plugin_table tbody');
+	tableEntryTemplate = tableBody.find('tr').clone();
+	tableBody.empty();
+
+	renderData(data);
+
+	$('#plugin_table').tablesorter( {
+		headers : {
+			0 : { sorter : 'digit' }
+		},
+		sortList : [ [ 1, 0 ] ],
+		textExtraction : mixedLinksExtraction
 	});
-}
\ No newline at end of file
+});
diff --git a/webconsole/src/main/resources/templates/components.html b/webconsole/src/main/resources/templates/components.html
index b995d31..a574b3e 100644
--- a/webconsole/src/main/resources/templates/components.html
+++ b/webconsole/src/main/resources/templates/components.html
@@ -5,9 +5,6 @@
 var scrData = ${__data__};
 // i18n
 var i18n = {
-	'Enable'           : '${scr.action.enable}',
-	'Disable'          : '${scr.action.disable}',
-	'Configure'        : '${scr.action.configure}',
 	'Bundle'           : '${scr.prop.bundle}',
 	'Default State'    : '${scr.prop.defstate}',
 	'Activation'       : '${scr.prop.activation}',
@@ -41,7 +38,20 @@
 		</tr>
 	</thead>
 	<tbody>
-		<tr><td colspan="4">&nbsp;</td></tr>
+		<tr>
+			<td>&nbsp;</td> <!-- id -->
+			<td> <!-- name with arrow -->
+				<div class="bIcon ui-icon ui-icon-triangle-1-e" style="float:left" title="${scr.details.tip}">&nbsp;</div>
+			</td> 
+			<td>&nbsp;</td> <!-- status -->
+			<td>
+				<ul class="icons">
+					<li class="dynhover ui-helper-hidden" title="${scr.action.enable}"><span class="ui-icon ui-icon-play">&nbsp;</span></li>
+					<li class="dynhover ui-helper-hidden" title="${scr.action.disable}"><span class="ui-icon ui-icon-stop">&nbsp;</span></li>
+					<li class="dynhover ui-helper-hidden" title="${scr.action.configure}"><span class="ui-icon ui-icon-wrench">&nbsp;</span></li>
+				</ul>
+			</td>
+		</tr>
 	</tbody>
 	</table>
 </div> <!-- end data available -->
diff --git a/webconsole/src/main/resources/templates/services.html b/webconsole/src/main/resources/templates/services.html
index bb84391..3919a65 100644
--- a/webconsole/src/main/resources/templates/services.html
+++ b/webconsole/src/main/resources/templates/services.html
@@ -13,7 +13,7 @@
 // data
 var bundlePath = "${bundlePath}";
 var drawDetails = ${drawDetails};
-renderServices(${__data__});
+var data = ${__data__};
 // ]]>
 </script>
 
@@ -30,7 +30,13 @@
 		</tr>
 	</thead>
 	<tbody>
-		<tr><td colspan="3">dummy</td></tr>
+		<tr>
+			<td>
+				<div class="bIcon ui-icon ui-icon-triangle-1-e" style="float:left" title="${services.details.tip}">&nbsp;</div>
+			</td>
+			<td>&nbsp;</td><!-- type -->
+			<td>&nbsp;</td><!-- bundle -->
+		</tr>
 	</tbody>
 </table>