You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rave.apache.org by jc...@apache.org on 2011/10/18 14:20:37 UTC

svn commit: r1185619 - in /incubator/rave/trunk: rave-portal-resources/src/main/webapp/WEB-INF/views/ rave-portal-resources/src/main/webapp/script/ rave-portal-resources/src/test/javascript/ rave-providers/rave-opensocial-provider/src/main/java/org/apa...

Author: jcian
Date: Tue Oct 18 12:20:36 2011
New Revision: 1185619

URL: http://svn.apache.org/viewvc?rev=1185619&view=rev
Log:
RAVE-269 - Widget Render Order

https://issues.apache.org/jira/browse/RAVE-269

Modified:
    incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/home.jsp
    incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave.js
    incubator/rave/trunk/rave-portal-resources/src/test/javascript/raveSpec.js
    incubator/rave/trunk/rave-providers/rave-opensocial-provider/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRenderer.java
    incubator/rave/trunk/rave-providers/rave-opensocial-provider/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java
    incubator/rave/trunk/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetRenderer.java
    incubator/rave/trunk/rave-providers/rave-w3c-provider/src/test/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetRendererTest.java

Modified: incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/home.jsp
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/home.jsp?rev=1185619&r1=1185618&r2=1185619&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/home.jsp (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/webapp/WEB-INF/views/home.jsp Tue Oct 18 12:20:36 2011
@@ -197,9 +197,8 @@
         </form>
     </div>        
     <script>
-        //Define the global widgets variable
-        //This array will be populated by RegionWidgetRender providers.
-        var widgets = [];
+        //Define the global widgets map.  This map will be populated by RegionWidgetRender providers.
+        var widgetsByRegionIdMap = {};
     </script>
     <portal:render-script location="${'BEFORE_LIB'}" />
     <script src="//cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
@@ -218,7 +217,7 @@
         $(function() {
             rave.setContext("<spring:url value="/app/" />");
             rave.initProviders();
-            rave.initWidgets(widgets);
+            rave.initWidgets(widgetsByRegionIdMap);
             rave.initUI();
             rave.layout.init();
         });

Modified: incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave.js
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave.js?rev=1185619&r1=1185618&r2=1185619&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave.js (original)
+++ incubator/rave/trunk/rave-portal-resources/src/main/webapp/script/rave.js Tue Oct 18 12:20:36 2011
@@ -488,6 +488,13 @@ var rave = rave || (function() {
 
     })();
 
+    function registerWidget(widgetsByRegionIdMap, regionId, widget) {
+        if (!widgetsByRegionIdMap.hasOwnProperty(regionId)) {
+            widgetsByRegionIdMap[regionId] = [];
+        }
+        widgetsByRegionIdMap[regionId].push(widget);
+    }
+
     function initializeProviders() {
         //Current providers are rave.wookie and rave.opensocial.
         //Providers register themselves when loaded, so
@@ -498,9 +505,33 @@ var rave = rave || (function() {
         }
     }
 
-    function initializeWidgets(widgets) {
+    function initializeWidgets(widgetsByRegionIdMap) {
+        //We get the widget objects in a map keyed by region ID.  The code below converts that map into a flat array
+        //of widgets with all the top widgets in each region first, then the seconds widgets in each region, then the
+        //third, etc until we have all widgets in the array.  This allows us to render widgets from left to right and
+        //top to bottom to give the best user experience possible (rendering the top widgets first).
+        //Note that this strategy relies on the javascript implementation to enumerate object properties in order:
+        //http://stackoverflow.com/questions/280713/elements-order-in-a-for-in-loop
+        //However this should at least get us to render the top "row" first, then the second "row", ... in any browser.
+        //If this turns out to be a major concern we can change the widgetsByRegionIdMap to a 2D array instead of a map.
+        var widgets = [];
+        for (var i = 0; ; i++) {
+            var foundGadgets = false;
+            for (var regionWidgets in widgetsByRegionIdMap) {
+                regionWidgets = widgetsByRegionIdMap[regionWidgets];
+                if (regionWidgets.length > i) {
+                    foundGadgets = true;
+                    widgets.push(regionWidgets[i]);
+                }
+            }
+
+            if (!foundGadgets) {
+                break;
+            }
+        }
+
         //Initialize the widgets for supported providers
-        for(var i=0; i<widgets.length; i++) {
+        for (var i = 0; i < widgets.length; i++) {
             var widget = widgets[i];
             initializeWidget(widget);
             widgetByIdMap[widget.regionWidgetId] = widget;
@@ -524,22 +555,6 @@ var rave = rave || (function() {
         }
     }
 
-    function mapWidgetsByType(widgets) {
-        var map = {};
-        for (var i = 0; i < widgets.length; i++) {
-            var widget = widgets[i];
-            var type = widget.type;
-            if (!type) {
-                type = "Unknown";
-            }
-            if (!map[type]) {
-                map[type] = [];
-            }
-            map[type].push(widget);
-        }
-        return map;
-    }
-
     function extractObjectIdFromElementId(elementId) {
         var tokens = elementId.split("-");
         return tokens.length > 2 && tokens[0] == "widget" || tokens[0] == "region" ? tokens[1] : null;
@@ -580,13 +595,21 @@ var rave = rave || (function() {
      */
     return {
         /**
+         * Registers the specified widget into the widgetsByRegionIdMap under the specified regionId.
+         * @param widgetsByRegionIdMap The map.
+         * @param regionId The regionId.
+         * @param widget The widget.
+         */
+        registerWidget : registerWidget,
+
+        /**
          * Initialize all of the registered providers
          */
         initProviders : initializeProviders,
 
         /**
          * Initializes the given set of widgets
-         * @param widgets a map of widgets by type
+         * @param widgets a map of widgets by regionId
          *
          * NOTE: widget object must have at a minimum the following properties:
          *      type,
@@ -600,13 +623,6 @@ var rave = rave || (function() {
         initUI : ui.init,
 
         /**
-         * Creates a map of widgets by their type
-         *
-         * @param widgets list of widgets to map by type
-         */
-        createWidgetMap : mapWidgetsByType,
-
-        /**
          * Parses the given string conforming to a rave object's DOM element ID and return
          * the RegionWidget id
          *

Modified: incubator/rave/trunk/rave-portal-resources/src/test/javascript/raveSpec.js
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-portal-resources/src/test/javascript/raveSpec.js?rev=1185619&r1=1185618&r2=1185619&view=diff
==============================================================================
--- incubator/rave/trunk/rave-portal-resources/src/test/javascript/raveSpec.js (original)
+++ incubator/rave/trunk/rave-portal-resources/src/test/javascript/raveSpec.js Tue Oct 18 12:20:36 2011
@@ -97,7 +97,8 @@ describe("Rave", function() {
         }
 
         it("calls the appropriate providers", function() {
-            var widgetList = [
+            var widgetsByRegionIdMap = {};
+            widgetsByRegionIdMap[1] = [
                     {type:"FOO"},
                     {type:"BAR"},
                     {type:"FOO"},
@@ -107,12 +108,68 @@ describe("Rave", function() {
             var provider2 = getMockProvider("BAR");
             rave.registerProvider(provider1);
             rave.registerProvider(provider2);
-            rave.initWidgets(widgetList);
+            rave.initWidgets(widgetsByRegionIdMap);
             expect(provider1.initWidgetsWasCalled(2)).toBeTruthy();
             expect(provider2.initWidgetsWasCalled(2)).toBeTruthy();
         });
+
+        it("renders widgets in the appropriate order (first 'row', second 'row', third 'row', ...)", function() {
+            var widgetsByRegionIdMap = {};
+            widgetsByRegionIdMap[1] = [
+                    {type:"FOO", renderOrder:1},
+                    {type:"FOO", renderOrder:4},
+                    {type:"FOO", renderOrder:7},
+                    {type:"FOO", renderOrder:9}
+            ];
+            widgetsByRegionIdMap[2] = [
+                    {type:"FOO", renderOrder:2},
+                    {type:"FOO", renderOrder:5},
+                    {type:"FOO", renderOrder:8},
+                    {type:"FOO", renderOrder:10},
+                    {type:"FOO", renderOrder:11},
+                    {type:"FOO", renderOrder:12}
+            ];
+            widgetsByRegionIdMap[3] = [
+                    {type:"FOO", renderOrder:3},
+                    {type:"FOO", renderOrder:6}
+            ];
+            var widgets = [];
+            var provider1 = getMockProvider("FOO");
+            var originalInitWidgetFunction = provider1.initWidget;
+            provider1.initWidget = function(widget) {
+                originalInitWidgetFunction(widget);
+                widgets.push(widget);
+            };
+            rave.registerProvider(provider1);
+            rave.initWidgets(widgetsByRegionIdMap);
+            expect(provider1.initWidgetsWasCalled(12)).toBeTruthy();
+
+            for (var i = 0; i < 12; i++) {
+                expect(widgets[i].renderOrder).toEqual(i+1);
+            }
+        });
+
+        it("puts widgets in buckets keyed by regionIds", function() {
+            var widgetsByRegionIdMap = {};
+            var regionOneKey = 1;
+            var regionTwoKey = 2;
+            rave.registerWidget(widgetsByRegionIdMap, regionOneKey, {arbitrary:"value"});
+            rave.registerWidget(widgetsByRegionIdMap, regionOneKey, {arbitrary:"value"});
+
+            rave.registerWidget(widgetsByRegionIdMap, regionTwoKey, {arbitrary:"value"});
+
+            rave.registerWidget(widgetsByRegionIdMap, regionOneKey, {arbitrary:"value"});
+            rave.registerWidget(widgetsByRegionIdMap, regionOneKey, {arbitrary:"value"});
+
+            rave.registerWidget(widgetsByRegionIdMap, regionTwoKey, {arbitrary:"value"});
+
+            expect(widgetsByRegionIdMap[regionOneKey].length).toEqual(4);
+            expect(widgetsByRegionIdMap[regionTwoKey].length).toEqual(2);
+        });
+
         it("Renders an error gadget when invalid widget is provided", function(){
-            var widgetList = [
+            var widgetsByRegionIdMap = {};
+            widgetsByRegionIdMap[1] = [
                     {type:"FOO",  regionWidgetId:20},
                     {type:"BAR",  regionWidgetId:21},
                     {type:"FOO",  regionWidgetId:22},
@@ -124,7 +181,7 @@ describe("Rave", function() {
             var provider2 = getMockProvider("BAR");
             rave.registerProvider(provider1);
             rave.registerProvider(provider2);
-            rave.initWidgets(widgetList);
+            rave.initWidgets(widgetsByRegionIdMap);
             expect($().expression()).toEqual("#widget-43-body");
             expect($().html()).toEqual("This widget type is currently unsupported.  Check with your administrator and be sure the correct provider is registered.");
             expect(provider1.initWidgetsWasCalled(2)).toBeTruthy();
@@ -132,56 +189,6 @@ describe("Rave", function() {
         });
     });
 
-    describe("createWidgetMap", function() {
-
-        it("builds a map keyed by type", function() {
-            var widgets = [
-                {regionWidgetId: 0, type: "OpenSocial"},
-                {regionWidgetId: 1, type: "OpenSocial"},
-                {regionWidgetId: 2, type: "W3C"},
-                {regionWidgetId: 3, type: "W3C"}
-            ];
-
-            var map = rave.createWidgetMap(widgets);
-
-            expect(map["OpenSocial"].length).toEqual(2);
-            expect(map["W3C"].length).toEqual(2);
-            expect(map["OpenSocial"]).toContain(widgets[1]);
-            expect(map["W3C"]).toContain(widgets[3]);
-        });
-
-        it("builds a map that has widgets under an Unknown key", function() {
-            var widgets = [
-                {regionWidgetId: 0, type: "OpenSocial"},
-                {regionWidgetId: 1, type: "OpenSocial"},
-                {regionWidgetId: 2, type: "W3C"},
-                {regionWidgetId: 3, type: "W3C"},
-                {regionWidgetId: 4 },
-                {regionWidgetId: 5, type: null }
-            ];
-
-            var map = rave.createWidgetMap(widgets);
-
-            expect(map["OpenSocial"].length).toEqual(2);
-            expect(map["W3C"].length).toEqual(2);
-            expect(map["Unknown"].length).toEqual(2);
-            expect(map["OpenSocial"]).toContain(widgets[1]);
-            expect(map["W3C"]).toContain(widgets[3]);
-            expect(map["Unknown"]).toContain(widgets[4]);
-        });
-
-        it("builds a map with no entries", function() {
-            var widgets = [];
-            var map = rave.createWidgetMap(widgets);
-            var count = 0;
-            for (i in map) {
-                count++;
-            }
-            expect(count).toEqual(0);
-        });
-
-    });
-
     describe("initUI", function() {
         function createMockJQuery() {
             var sortableArgs = null;

Modified: incubator/rave/trunk/rave-providers/rave-opensocial-provider/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRenderer.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-providers/rave-opensocial-provider/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRenderer.java?rev=1185619&r1=1185618&r2=1185619&view=diff
==============================================================================
--- incubator/rave/trunk/rave-providers/rave-opensocial-provider/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRenderer.java (original)
+++ incubator/rave/trunk/rave-providers/rave-opensocial-provider/src/main/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRenderer.java Tue Oct 18 12:20:36 2011
@@ -62,13 +62,13 @@ public class OpenSocialWidgetRenderer im
     //Note the widgets.push() call.  This defines the widget objects, which are
     //added to the widgets[] array in home.jsp.
     private static final String SCRIPT_BLOCK =
-            "<script>widgets.push({type: '%1$s'," +
-            " regionWidgetId: %2$s," +
-            " widgetUrl: '%3$s', " +
-            " securityToken: '%4$s', " +
-            " metadata: %5$s," +
-            " userPrefs: %6$s," +
-            " collapsed: %7$s});</script>";
+            "<script>rave.registerWidget(widgetsByRegionIdMap, %1$s, {type: '%2$s'," +
+            " regionWidgetId: %3$s," +
+            " widgetUrl: '%4$s', " +
+            " securityToken: '%5$s', " +
+            " metadata: %6$s," +
+            " userPrefs: %7$s," +
+            " collapsed: %8$s});</script>";
     private static final String MARKUP = "<!-- RegionWidget %1$s placeholder -->";
 
     @Override
@@ -110,8 +110,8 @@ public class OpenSocialWidgetRenderer im
             }
         }
 
-        return String.format(SCRIPT_BLOCK, Constants.WIDGET_TYPE, item.getEntityId(), item.getWidget().getUrl(),
-                securityTokenService.getEncryptedSecurityToken(item),
+        return String.format(SCRIPT_BLOCK, item.getRegion().getEntityId(), Constants.WIDGET_TYPE, item.getEntityId(),
+                item.getWidget().getUrl(), securityTokenService.getEncryptedSecurityToken(item),
                 openSocialService.getGadgetMetadata(item.getWidget().getUrl()), userPrefs.toString(), item.isCollapsed());
     }
 }
\ No newline at end of file

Modified: incubator/rave/trunk/rave-providers/rave-opensocial-provider/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-providers/rave-opensocial-provider/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java?rev=1185619&r1=1185618&r2=1185619&view=diff
==============================================================================
--- incubator/rave/trunk/rave-providers/rave-opensocial-provider/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java (original)
+++ incubator/rave/trunk/rave-providers/rave-opensocial-provider/src/test/java/org/apache/rave/provider/opensocial/web/renderer/OpenSocialWidgetRendererTest.java Tue Oct 18 12:20:36 2011
@@ -20,6 +20,7 @@
 package org.apache.rave.provider.opensocial.web.renderer;
 
 import org.apache.rave.exception.NotSupportedException;
+import org.apache.rave.portal.model.Region;
 import org.apache.rave.portal.model.RegionWidget;
 import org.apache.rave.portal.model.RegionWidgetPreference;
 import org.apache.rave.portal.model.Widget;
@@ -77,16 +78,18 @@ public class OpenSocialWidgetRendererTes
         w.setEntityId(1L);
         w.setType(Constants.WIDGET_TYPE);
         w.setUrl(VALID_GADGET_URL);
+        Region region = new Region(1L);
         RegionWidget rw = new RegionWidget();
         rw.setEntityId(1L);
         rw.setCollapsed(VALID_COLLAPSED);
         rw.setWidget(w);
+        rw.setRegion(region);
         rw.setPreferences(Arrays.asList(new RegionWidgetPreference(1L, 1L, "color", "blue"),
                                         new RegionWidgetPreference(2L, 1L, "speed", "fast"),
                                         new RegionWidgetPreference(3L, 1L, null, null)));
 
         final String markup =
-            "<script>widgets.push({type: 'OpenSocial'," +
+            "<script>rave.registerWidget(widgetsByRegionIdMap, 1, {type: 'OpenSocial'," +
             " regionWidgetId: 1," +
             " widgetUrl: '" + VALID_GADGET_URL +"', " +
             " securityToken: '" + VALID_SECURITY_TOKEN + "', " +
@@ -111,13 +114,15 @@ public class OpenSocialWidgetRendererTes
     public void render_null() {
         Widget w = new Widget();
         w.setType(Constants.WIDGET_TYPE);
+        Region region = new Region(1L);
         RegionWidget rw = new RegionWidget();
         rw.setWidget(w);
+        rw.setRegion(region);
 
         String result = renderer.render(rw, null);
 
         final String markup =
-            "<script>widgets.push({type: 'OpenSocial'," +
+            "<script>rave.registerWidget(widgetsByRegionIdMap, 1, {type: 'OpenSocial'," +
             " regionWidgetId: null," +
             " widgetUrl: 'null', " +
             " securityToken: '" + VALID_SECURITY_TOKEN + "', " +

Modified: incubator/rave/trunk/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetRenderer.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetRenderer.java?rev=1185619&r1=1185618&r2=1185619&view=diff
==============================================================================
--- incubator/rave/trunk/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetRenderer.java (original)
+++ incubator/rave/trunk/rave-providers/rave-w3c-provider/src/main/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetRenderer.java Tue Oct 18 12:20:36 2011
@@ -38,9 +38,9 @@ import static org.apache.rave.provider.w
 public class W3cWidgetRenderer implements RegionWidgetRenderer {
 
 
-    private static final String IFRAME_MARKUP = "widgets.push({type: '%1$s'," +
-                                                " regionWidgetId: %2$s," +
-                                                " widgetUrl: '%3$s'});";
+    private static final String IFRAME_MARKUP = "<script>rave.registerWidget(widgetsByRegionIdMap, %1$s, {type: '%2$s'," +
+                                                " regionWidgetId: %3$s," +
+                                                " widgetUrl: '%4$s'});</script>";
 
     private static final String INLINE_MARKUP = "";
 
@@ -71,6 +71,6 @@ public class W3cWidgetRenderer implement
         }
         Widget contextualizedWidget = widgetService.getWidget(null, null, widget);
         String url = contextualizedWidget == null ? null : contextualizedWidget.getUrl();
-        return String.format(IFRAME_MARKUP, WIDGET_TYPE, item.getEntityId(), url);
+        return String.format(IFRAME_MARKUP, item.getRegion().getEntityId(), WIDGET_TYPE, item.getEntityId(), url);
     }
 }

Modified: incubator/rave/trunk/rave-providers/rave-w3c-provider/src/test/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetRendererTest.java
URL: http://svn.apache.org/viewvc/incubator/rave/trunk/rave-providers/rave-w3c-provider/src/test/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetRendererTest.java?rev=1185619&r1=1185618&r2=1185619&view=diff
==============================================================================
--- incubator/rave/trunk/rave-providers/rave-w3c-provider/src/test/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetRendererTest.java (original)
+++ incubator/rave/trunk/rave-providers/rave-w3c-provider/src/test/java/org/apache/rave/provider/w3c/web/renderer/W3cWidgetRendererTest.java Tue Oct 18 12:20:36 2011
@@ -20,6 +20,7 @@
 package org.apache.rave.provider.w3c.web.renderer;
 
 import org.apache.rave.exception.NotSupportedException;
+import org.apache.rave.portal.model.Region;
 import org.apache.rave.portal.model.RegionWidget;
 import org.apache.rave.portal.model.Widget;
 import org.apache.rave.portal.service.WidgetProviderService;
@@ -58,9 +59,11 @@ public class W3cWidgetRendererTest {
         Widget w = new Widget();
         w.setType(Constants.WIDGET_TYPE);
         w.setUrl("http://example.com/widgets/1");
+        Region region = new Region(1L);
         RegionWidget rw = new RegionWidget();
         rw.setEntityId(1L);
         rw.setWidget(w);
+        rw.setRegion(region);
 
         Widget wookieWidget = new Widget();
         final String WIDGET_INSTANCE = "http://example.com/widgetinstances/1";
@@ -79,8 +82,10 @@ public class W3cWidgetRendererTest {
     public void render_null() {
         Widget w = new Widget();
         w.setType(Constants.WIDGET_TYPE);
+        Region region = new Region(1L);
         RegionWidget rw = new RegionWidget();
         rw.setWidget(w);
+        rw.setRegion(region);
 
         String result = renderer.render(rw, null);
         assertThat(result.matches(".*regionWidgetId[ ]*:[ ]*null,.*"), is(true));