Render Template cell name in DOM as css class

This enables cell styling using native browser CSS, making the template
engine condsiderably more powerful without introducing new API or
affecting other clients. (API for adding style sheets to the web client
would be useful.)

Change-Id: Ifb109e7feb5ccf309f25c158791b267be2b204ad
Signed-off-by: Tim Buschtöns <tbuschto@eclipsesource.com>
diff --git a/bundles/org.eclipse.rap.rwt/js/rwt/widgets/util/CellRendererRegistry.js b/bundles/org.eclipse.rap.rwt/js/rwt/widgets/util/CellRendererRegistry.js
index c442be5..ff35a98 100644
--- a/bundles/org.eclipse.rap.rwt/js/rwt/widgets/util/CellRendererRegistry.js
+++ b/bundles/org.eclipse.rap.rwt/js/rwt/widgets/util/CellRendererRegistry.js
@@ -59,6 +59,9 @@
       result.style.overflow = "hidden";
       // NOTE : older IE can (in quirksmode) not deal with multiple css classes!
       var cssClass = cellData.selectable ? "rwt-cell-selectable" : "rwt-cell";
+      if( isValidCssClass( cellData.name ) ) {
+        cssClass += " " + cellData.name;
+      }
       if( rwt.client.Client.isMshtml() ) {
         result.className = cssClass;
       } else {
@@ -77,6 +80,15 @@
 
 };
 
+var isValidCssClass = function( name ) {
+  if( name && name.length > 1 ) {
+    return    name.charAt( 0 ).match( /[a-zA-Z]/ )
+           && name.match( /^[a-zA-Z0-9_-]*$/ );
+  } else {
+    return false;
+  }
+};
+
 rwt.widgets.util.CellRendererRegistry.getInstance = function() {
   return rwt.runtime.Singletons.get( rwt.widgets.util.CellRendererRegistry );
 };
diff --git a/examples/org.eclipse.rap.examples/src/org/eclipse/rap/examples/internal/ExampleApplication.java b/examples/org.eclipse.rap.examples/src/org/eclipse/rap/examples/internal/ExampleApplication.java
index 6f8eee8..a5e161f 100644
--- a/examples/org.eclipse.rap.examples/src/org/eclipse/rap/examples/internal/ExampleApplication.java
+++ b/examples/org.eclipse.rap.examples/src/org/eclipse/rap/examples/internal/ExampleApplication.java
@@ -35,6 +35,7 @@
     Map<String, String> properties = new HashMap<String, String>();
     properties.put( WebClient.PAGE_TITLE, "RAP Examples" );
     properties.put( WebClient.BODY_HTML, readTextFromResource( "resources/body.html", "UTF-8" ) );
+    properties.put( WebClient.HEAD_HTML, readTextFromResource( "resources/head.html", "UTF-8" ) );
     properties.put( WebClient.FAVICON, "icons/favicon.png" );
     application.setOperationMode( OperationMode.SWT_COMPATIBILITY );
     application.addEntryPoint( "/", MainUi.class, properties );
diff --git a/examples/org.eclipse.rap.examples/src/resources/head.html b/examples/org.eclipse.rap.examples/src/resources/head.html
new file mode 100644
index 0000000..cee7ae5
--- /dev/null
+++ b/examples/org.eclipse.rap.examples/src/resources/head.html
@@ -0,0 +1,8 @@
+<style type="text/css">
+.arrow {
+  visibility: hidden;
+}
+div:hover > .arrow {
+  visibility: visible;
+}
+</style>
\ No newline at end of file
diff --git a/tests/org.eclipse.rap.rwt.jstest/js/org/eclipse/rwt/test/tests/CellRendererRegistryTest.js b/tests/org.eclipse.rap.rwt.jstest/js/org/eclipse/rwt/test/tests/CellRendererRegistryTest.js
index 75440fc..77b5915 100644
--- a/tests/org.eclipse.rap.rwt.jstest/js/org/eclipse/rwt/test/tests/CellRendererRegistryTest.js
+++ b/tests/org.eclipse.rap.rwt.jstest/js/org/eclipse/rwt/test/tests/CellRendererRegistryTest.js
@@ -148,6 +148,39 @@
       assertEquals( "rwt-cell-selectable", element.className || element.getAttribute( "class" ) );
     },
 
+    testAddFunctionCreateElement_ForNamedCell : function() {
+      registry.add(  {
+        "cellType" : "foo",
+        "contentType" : "bar",
+        "renderContent" : function(){}
+      } );
+
+      var element = registry.getRendererFor( "foo" ).createElement( { "name" :  "foo_bar-1"} );
+      assertEquals( "rwt-cell foo_bar-1", element.className || element.getAttribute( "class" ) );
+    },
+
+    testAddFunctionCreateElement_ForNamedCellNotStartingWithLetter : function() {
+      registry.add(  {
+        "cellType" : "foo",
+        "contentType" : "bar",
+        "renderContent" : function(){}
+      } );
+
+      var element = registry.getRendererFor( "foo" ).createElement( { "name" :  "1foobar"} );
+      assertEquals( "rwt-cell", element.className || element.getAttribute( "class" ) );
+    },
+
+    testAddFunctionCreateElement_ForNamedCellContainingInvalidCharacer : function() {
+      registry.add(  {
+        "cellType" : "foo",
+        "contentType" : "bar",
+        "renderContent" : function(){}
+      } );
+
+      var element = registry.getRendererFor( "foo" ).createElement( { "name" :  "foo$bar"} );
+      assertEquals( "rwt-cell", element.className || element.getAttribute( "class" ) );
+    },
+
     testGetAll : function() {
       registry.add( {
         "cellType" : "bar1",