ICEfaces
  1. ICEfaces
  2. ICE-2657

Using Liferay portlet close widget to dynamically remove ICEfaces portlets results in bridge JS error

    Details

    • Type: Task Task
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Invalid
    • Affects Version/s: 1.6
    • Fix Version/s: None
    • Component/s: Bridge
    • Labels:
      None
    • Environment:
      Liferay Portal 4.3.x, ICEfaces portlets in async mode.
    • Affects:
      Compatibility/Configuration
    • Workaround Exists:
      Yes
    • Workaround Description:
      Hide
      There is a viable solution for this as of Liferay 5.1.0 (http://support.liferay.com/browse/LEP-6428).

      To subscribe to the close portlet event you would type:

      Liferay.Publisher.subscribe(
      'closePortlet',
      fn,
      [scope]
      );

      The first parameter is the event that is subscribed, in this case closePortlet. The next parameter is a function that will be executed when the portlet is closed, and the third parameter is option, and it's an object that sets the scope that you wish to execute your Javascript in. So for instance, if you wanted to remap the this object in the function you're passing in, you would pass that object. But of course, it's optional.

      Here is an example of how you would use it:

      Liferay.Publisher.subscribe(
      'closePortlet',
      function (plid, portletId) {
      console.log(plid, portletId);
      }
      );

      Now that the API is available on the client side for disposing of views, the developer can add a version following script to the portlet to enable disposing of a View when the portlet is closed via the portlet window widget. The script id attribute should be unique for each portlet but match the value in the line

      var e = 'id1234'.asElement();


      //Portlet script

              <script id="id1234" type="text/javascript">
                  //this function filters executes the callback function only if the 'e' element is included in the closed portlet
                  //function created to factored into a library
                  function filterEvent(element, callback) {
                      return function(p) {
                          var id = '_' + p.portletId + '_';
                          var parent = element;
                          while (parent) {
                              if (parent.id == id) {
                                  callback();
                                  break;
                              } else {
                                  parent = parent.parentNode;
                              }
                          }
                      }
                  }

                  if (Liferay.Publisher) {
                      var e = 'id1234'.asElement();
                      Liferay.Publisher.subscribe('closePortlet', filterEvent(e, function() {
                          $element(e).findBridge().disposeAndNotify();
                      }));
                  }
              </script>
      Show
      There is a viable solution for this as of Liferay 5.1.0 ( http://support.liferay.com/browse/LEP-6428 ). To subscribe to the close portlet event you would type: Liferay.Publisher.subscribe( 'closePortlet', fn, [scope] ); The first parameter is the event that is subscribed, in this case closePortlet. The next parameter is a function that will be executed when the portlet is closed, and the third parameter is option, and it's an object that sets the scope that you wish to execute your Javascript in. So for instance, if you wanted to remap the this object in the function you're passing in, you would pass that object. But of course, it's optional. Here is an example of how you would use it: Liferay.Publisher.subscribe( 'closePortlet', function (plid, portletId) { console.log(plid, portletId); } ); Now that the API is available on the client side for disposing of views, the developer can add a version following script to the portlet to enable disposing of a View when the portlet is closed via the portlet window widget. The script id attribute should be unique for each portlet but match the value in the line var e = 'id1234'.asElement(); //Portlet script         <script id="id1234" type="text/javascript">             //this function filters executes the callback function only if the 'e' element is included in the closed portlet             //function created to factored into a library             function filterEvent(element, callback) {                 return function(p) {                     var id = '_' + p.portletId + '_';                     var parent = element;                     while (parent) {                         if (parent.id == id) {                             callback();                             break;                         } else {                             parent = parent.parentNode;                         }                     }                 }             }             if (Liferay.Publisher) {                 var e = 'id1234'.asElement();                 Liferay.Publisher.subscribe('closePortlet', filterEvent(e, function() {                     $element(e).findBridge().disposeAndNotify();                 }));             }         </script>

      Description

      This can be reproduced fairly easily. It's an issue with running on Liferay because Liferay supports dynamically adding and removing portlets from the page. What I believe happens is this:

      1) Add an ICEfaces portlet to an empty portal page - just one will do. This causes our JavaScript to be downloaded and executed and the heartbeat to start. Wait for the first successful ping/pong to ensure things are working correctly.

      2) Remove the portlet from the page using the window's close icon (only available on Liferay). Again wait for the ping/pong. In Firebug, you'll see this message:

      [window.0BnX#10.async-connection] receive broadcast failed TypeError: this.elementID.asElement() has no propertiesicefaces-d2d.js (line 1337)

      Our JavaScript bridge + heartbeat is still running. It doesn't get unloaded when the portlet went away. Not even sure that we can detect this in a non-proprietary way.

      This currently won't occur with most of the other portals (like JBoss or Pluto) because to add/remove portlets on those platforms requires you to go to an Admin page of some sort which unloads our page (stopping all the JS). JBoss doesn't give you the option of a close button as a window decoration. Once you're done with the Admin page and go back to the portal page, everything starts fresh so there's no "leftover" JavaScript running.

      We need to discuss this with Liferay to determine the best course of action.

        Issue Links

          Activity

          Hide
          Neil Griffin added a comment -

          I just tried to reproduce this problem with ICEfaces 1.7RC1 and Liferay 4.4.2 and did not see the JavaScript error in FireFox.

          Is this still an issue?

          If it is, then I thought it best to record here a summary of the IM discussion I had with Derek on this issue back on 1/22/2008:

          Derek explained the problem a little further:
          "If you close one, the bridge has no way of knowing and throws JavaScript errors. It's trying to maintain the portlet that went missing. It's the reverse problem of adding it dynamically."

          Derek presented the following two ideas as potential solutions:
          1. Force the page to reload when the portlet is removed from the page
          2. Hook into the Liferay JavaScript API and receive notifications for when a portlet is removed from a page

          Liferay doesn't have a means to do #1. Regarding #2, I got on IM with Liferay's Nate Cavanaugh, and he said that there is currently no mechanism in the Liferay javascript API to register a listener to hear when a portlet is removed from the page. However, he wrote that he has wanted to do that for a long time, and it would be super easy to do.

          If this is still an issue then I'll get back with Nate and see if we can't get #2 implemented.

          Show
          Neil Griffin added a comment - I just tried to reproduce this problem with ICEfaces 1.7RC1 and Liferay 4.4.2 and did not see the JavaScript error in FireFox. Is this still an issue? If it is, then I thought it best to record here a summary of the IM discussion I had with Derek on this issue back on 1/22/2008: Derek explained the problem a little further: "If you close one, the bridge has no way of knowing and throws JavaScript errors. It's trying to maintain the portlet that went missing. It's the reverse problem of adding it dynamically." Derek presented the following two ideas as potential solutions: 1. Force the page to reload when the portlet is removed from the page 2. Hook into the Liferay JavaScript API and receive notifications for when a portlet is removed from a page Liferay doesn't have a means to do #1. Regarding #2, I got on IM with Liferay's Nate Cavanaugh, and he said that there is currently no mechanism in the Liferay javascript API to register a listener to hear when a portlet is removed from the page. However, he wrote that he has wanted to do that for a long time, and it would be super easy to do. If this is still an issue then I'll get back with Nate and see if we can't get #2 implemented.
          Hide
          Neil Griffin added a comment -

          I sent Nate an email and he gave me an update – the listening feature in #2 above has been implemented in the Liferay trunk and will appear in Liferay 5.0. Here are his instructions:

          To subscribe to the close portlet event you would type:

          Liferay.Publisher.subscribe(
          'closePortlet',
          fn,
          [scope]
          );

          The first parameter is the event that is subscribed, in this case closePortlet. The next parameter is a function that will be executed when the portlet is closed, and the third parameter is option, and it's an object that sets the scope that you wish to execute your Javascript in. So for instance, if you wanted to remap the this object in the function you're passing in, you would pass that object. But of course, it's optional.

          Here is an example of how you would use it:

          Liferay.Publisher.subscribe(
          'closePortlet',
          function (plid, portletId)

          { console.log(plid, portletId); }

          );

          Show
          Neil Griffin added a comment - I sent Nate an email and he gave me an update – the listening feature in #2 above has been implemented in the Liferay trunk and will appear in Liferay 5.0. Here are his instructions: To subscribe to the close portlet event you would type: Liferay.Publisher.subscribe( 'closePortlet', fn, [scope] ); The first parameter is the event that is subscribed, in this case closePortlet. The next parameter is a function that will be executed when the portlet is closed, and the third parameter is option, and it's an object that sets the scope that you wish to execute your Javascript in. So for instance, if you wanted to remap the this object in the function you're passing in, you would pass that object. But of course, it's optional. Here is an example of how you would use it: Liferay.Publisher.subscribe( 'closePortlet', function (plid, portletId) { console.log(plid, portletId); } );
          Hide
          Deryk Sinotte added a comment -

          We can do one of two things here:

          1) Document it as something for the developer to add themselves. However, we'll have to also document what they should do (i.e. what ICEfaces API they should call) when a portlet is removed so that the ICEfaces bridge can do what it needs to do.

          2) We can add this Liferay specific code to our bridge so that it's only executed in the appropriate environment. This is obviously more transparent for the developer but it also means adding platform specific code to the bridge. There are different ways to do that as well. We can include it always or do something more dynamic or offer some sort of configuration switch for the developer so they can turn it on if they need it since dynamically adding/removing portlets is not always available to all users.

          Show
          Deryk Sinotte added a comment - We can do one of two things here: 1) Document it as something for the developer to add themselves. However, we'll have to also document what they should do (i.e. what ICEfaces API they should call) when a portlet is removed so that the ICEfaces bridge can do what it needs to do. 2) We can add this Liferay specific code to our bridge so that it's only executed in the appropriate environment. This is obviously more transparent for the developer but it also means adding platform specific code to the bridge. There are different ways to do that as well. We can include it always or do something more dynamic or offer some sort of configuration switch for the developer so they can turn it on if they need it since dynamically adding/removing portlets is not always available to all users.
          Hide
          Mircea Toma added a comment -

          ICE-3266 resolution provides the necessary API for notifying ICEfaces when portlets are removed from a page. The example provided should be working once http://support.liferay.com/browse/LEP-6428 issue is resolved.

          Show
          Mircea Toma added a comment - ICE-3266 resolution provides the necessary API for notifying ICEfaces when portlets are removed from a page. The example provided should be working once http://support.liferay.com/browse/LEP-6428 issue is resolved.
          Hide
          Ken Fyten added a comment -

          Marking as Closed / Invalid as part of legacy ICEfaces 1.x, 2.x JIRA cleanup.

          Note: This issue may be resolved in a newer ICEfaces release, available here: http://www.icesoft.org/java/downloads/icefaces-downloads.jsf

          If the issue persists with the current ICEfaces release, please create a new JIRA for it.

          Show
          Ken Fyten added a comment - Marking as Closed / Invalid as part of legacy ICEfaces 1.x, 2.x JIRA cleanup. Note: This issue may be resolved in a newer ICEfaces release, available here: http://www.icesoft.org/java/downloads/icefaces-downloads.jsf If the issue persists with the current ICEfaces release, please create a new JIRA for it.

            People

            • Assignee:
              Unassigned
              Reporter:
              Ken Fyten
            • Votes:
              1 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: