Help

Today I'd like to post a really simple solution which is frequently asked at RichFaces Users forum threads. Two questions which can be solved by using this solution:

  • Can the RichFaces popup component be non-modal?
  • Can the rich:panel component be draggable/resizable?

As you can guess I'll use the rich:modalPanel component in order to answer both questions, and the solution is really simple and relies on RichFaces special rich css classes.

Standard Modal Panel look and feel

At first we should open RichFaces developer guide and look to the modal panel skinability section. There we could find the rich-mpnl-mask-div style class which is applied to the page blocking div element for all the modal panels.

Now we can just to add

styleClass="noMaskClass"
to the rich:modalPanel component that we want to be non-modal. And then add the next simple css selector to the stylesheet used by the page:
.noMaskClass .rich-mpnl-mask-div{
    display:none;
}
So the richfaces-demo Modal Panel sample (second one) code changed to:
<style>
    .noMaskClass .rich-mpnl-mask-div{
        display:none;
    }
</style>
<rich:modalPanel  id="mp" minHeight="200" minWidth="450" styleClass="noMaskClass"
    height="200" width="500">
        //Panel Content
</rich:modalPanel>
Modal Panel with removed page blocking div

And if as a result panel in first sample opens as modal, and panel in second sample opens as non modal. So we have the panel with the resizability, autosize, moving, show/hide API and so on features..

So far so good.. But after simple tests we could see that this code works fine in all browsers in Windows environment except IE (Js error appears) and typing restricted in the parent page inputs in FF at linux environment.

After short investigation I found that that forgot about the modal panel client side methods which gets invoked in order to control the focus and tabbing. (accessing the parent page controls using tab control gets restricted using the methods.) But we not need these methods to be invoked at all if our panel is non-modal. So we should just override the methods with empty ones in order to get it working fine.

This is code of the function which will get the modal panel JS object and override needed methods:

function removeTabHandlingFromPanel(modalPanelComponent){
     modalPanelComponent.lastOnfocus = function(event){};
     modalPanelComponent.firstOnfocus = function(event){};
     modalPanelComponent.processAllFocusElements = function(event){};
     modalPanelComponent.processTabindexes = function(event){};
     modalPanelComponent.restoreTabindexes = function(event){};
     modalPanelComponent.preventFocus = function(event){};
     modalPanelComponent.restoreFocus = function(event){};
}
And now we will call this function for the panel which marked as non modal with noMask styleClass
removeTabHandlingFromPanel(#{rich:component('mp')});
So, finally solution is done and works fine within all the browsers supported with RichFaces.

12 comments:
 
27. May 2009, 23:42 CET | Link
Arbi Sookazian

Ilya, interesting post, thx for sharing!

Can the rich:panel component be draggable/resizable?

do you mean rich:modalPanel rather than rich:panel above?

Have you guys started testing your components and solutions/tips like these using IE 8? I've noticed a lot of issues when using RF and IE (which is our corporate standard).

I would also suggest that tips like this need to be centralized in one repository/forum/wiki, etc. so it's easier for us RF/Seam developers to find and use them.

ReplyQuote
 
29. May 2009, 21:55 CET | Link

Hi!

Can the rich:panel component be draggable/resizable? do you mean rich:modalPanel rather than rich:panel above?

yes :)

Have you guys started testing your components and solutions/tips like these using IE 8? I've noticed a lot of issues when using RF and IE (which is our corporate standard).

First IE8 testing started before 3.3.1 release after IE released. Now we continue our stabilization work in this direction.

I would also suggest that tips like this need to be centralized in one repository/forum/wiki, etc. so it's easier for us RF/Seam developers to find and use them.

Already working on that :) I mean new official page and more structurized wiki pages which will be more convinient to be used by the community and team both.

 
30. Aug 2009, 03:44 CET | Link
warmen

I'm creating the modalpanel dynamically in the bean, by calling the method from a a4j:commandLink, and calling removeTabHandlingFromPanel(modalPanelComponent) on the oncomplete event for this commandLink, but I'm having the same error Can't move focus to the control because it is invisible, not enabled, or of a type that does not accept the focus described above. Is there any workaround on this?

 
27. Sep 2009, 02:13 CET | Link
Juan

The removeTabHandlingFromPanel must be executed just after the rich:modalPanel. I am doing like that and works with no errors.

 
10. Nov 2009, 22:17 CET | Link
Leandro

Congratulations for this post

 
13. Nov 2009, 20:04 CET | Link
Tharves
In the sencond example, where can i use removeTabHandlingFromPanel()


I changed tag panel id="mp" minHeight="200" minWidth="450" styleClass="noMaskClass" height="200" width="500"

instead of modalPanel id="mp" minHeight="200" minWidth="450" styleClass="noMaskClass"
    height="200" width="500"

please help me
 
16. Nov 2009, 20:10 CET | Link
Tharves

Please any one help me!!!!!!!!!!

can you give the sample code of the above issue.

i am getting modelPanel.js not implemented error.

 
31. Dec 2009, 03:19 CET | Link

Hi Ilya,

Great post.

Fully working under FF 3 But not working under IE7

.noMaskClass .rich-mpnl-mask-div{ display:none; }

Indeed noMaskClass makes the modalPanel not visible at all. if you set .noMaskClass .rich-mpnl-mask-div-opaque{ display:none; } it is better under IE (at least the modal shows up), BUT is not working under FF anymore

do you think of a workaround for this... thanks

 
31. Dec 2009, 16:47 CET | Link
Nicog

Found the solution fully working on FF and IE

Do not use noMaskClass and use the following function just after

#{rich:component('mpId')}.show();

Function in script tag

function removeTabHandlingFromPanel(modalPanelId){
                 var  modalPanelComponent = document.getElementById(modalPanelId).component;
                 modalPanelComponent.lastOnfocus = function(event){return;};
                 modalPanelComponent.firstOnfocus = function(event){return;};
                 modalPanelComponent.processAllFocusElements = function(event){return;};
                 modalPanelComponent.processTabindexes = function(event){return;};
                 modalPanelComponent.restoreTabindexes = function(event){return;};
                 modalPanelComponent.preventFocus = function(event){return;};
                 modalPanelComponent.restoreFocus = function(event){return;};
                 document.getElementById(modalPanelId+'Div').style.display="none";
                 document.getElementById(modalPanelId+'CursorDiv').style.display="none";
            }

SO it ends to (mpId show be the clientId)

#{rich:component('mpId')}.show();removeTabHandlingFromPanel('mpId');

regards and have a happy new year all

 
08. Jun 2010, 09:51 CET | Link
soft developer

Can we apply onmaskclick event on non-modal panel??YneduW

 
18. Aug 2011, 04:06 CET | Link
Dragan

Problem in IE6(i know, but stack with having to support it)...select lists get disabled after the non-modal panel as described is shown...

 
18. Aug 2011, 04:12 CET | Link
Dragan

Also, using the focus attribute causes the js error in IE6 if the destination component is disabled...generated JS code should have just caught and ignored the error...this poses a big problem when trying to use invisible modal panel on an ajax request, causing the select list to became disabled temporarily, but focus executes before the modal panel is released, causing JS error in IE6...just plain discouraging and dissapointing behaviour.

Post Comment