Blog Archives

July 26th, 2011
10:31 am
Extra unwanted margin around an HTML textarea in Google Chrome

Posted under CSS
Tags , , , , , ,

Chrome places an unwanted 4px bottom margin on a textarea, which is impossible to elminate purely by the margin settings.

In addition, the other browsers sometimes have related issues.

This post on StackOverflow discusses the issue, and the Chrome bug issue may be found here.

Issues like this can be caused in inline and inline-block elements, due to side effects of the line height/vertical alignment of textual elements. They can be hard issues to diagnose as the cause of the extra margin is not readily visible in tools like Firebug or Chrome’s developer tools/debugger. In order to see it, I added an extra div with a border around the element, and the margin was then clearly visible, but of course it was still not reported as a margin on the textarea element, which steadfastly maintained its story that no margin was present!

As per the StackOverflow article, there are 2 ways around this issue:-

  • If the textarea is set to have vertical-align:top then this eliminates the problem. It also has the advantage of maintaining the element as inline-block – in Chrome’s case this is the default, and with other browsers this will often be used in order to allow margins etc. which an inline element will not allow.
  • Another fix for the problem is to set the textarea to display:block, i.e. to make it a block element. This is fine, but it should be noted that as the element is not natively a block type element, IE7 and earlier IE versions will not handle this. IE8 and IE9 will allow an inline element to be redesignated as a block one. Therefore, the first method has better browser compatibility.

No Comments »

July 19th, 2011
5:00 pm
Sync issues between TyTn II and Windows 7/Windows Mobile Device Center

Posted under 64 Bit
Tags , , , , ,

My old TyTn II has had sync issues over the last few weeks, sometimes needing several attempts to sync.

A few days ago it failed completely with sync errors part way through.

I have tried a number of things to resolve the issue, with only partial success.

1/ WMDC 6.1 did not sync at all. I tried turning ‘advanced network functionality’ both on and off on the TyTn II (under settings/connections/USB to PC), and neither worked. The advanced setting is apparently what allows the device to share the PCs internet connection, and is not available with this turned off, although I have not investigated this.

2/ I tried removing WMDC 6.1 and installing WMDC6.0 for Windows 7/Vista 64 bit, but it always installed 6.1 as part of the install, and so was very tricky to roll back.

3/ This procedure worked in the end and allowed 6.0 to install (as per this forum post here):-

Note that as part of this procedure, when deleting the WindowsMobile folder, renaming it first then allows all the contents to be deleted (possibly rebooting after the rename but this was not always required). Note also that I turned windows update automatic mode off so that it would always ask about any update first, in case it was responsible for the ‘invisible’ update to 6.1

Here are the steps that I performed during this cycle of events that has got
my Dopod phone with WM6 sync’ing again with WMDC 6.0:
— Uninstalled the two Windows Mobile Device Center 6.1 items from the
Control Panel > Programs and Features list
— Manually deleted the contents of the C:\Windows\WindowsMobile folder.
Initially I could not delete some DLLs but once the two “Windows Mobile
device connectivity” services were stopped from the Task Manager, I was able
to delete the rest of the files in the WindowsMobile folder, except for the
en-US folder containing the *.MUI files. I could not delete them and so
decided to leave them.
— Using Regedit, I deleted all entries from the following two keys that
related to my two devices:
* HKCU\Software\Microsoft\Windows CE Services\Partners
* HKLM\Software\Microsoft\Windows Portable Devices\Devices (I left
in the entry for my memory card)
— Using Windows Explorer, I deleted all files in the following folder:
* C:\Users\<username>\AppData\Roaming\Microsoft\Acti veSync\Profiles
— With my two Pocket PCs disconnected, I tapped on Start > Programs >
ActiveSync > Menu > Options, highlighted the Windows PC and tapped on and
the Delete button. Both of my PPCs had two entries in here so there could
have been some confusion on the desktop at some point, so I deleted both of
them. They do not sync with any other computer.
— Rebooted (Restarted) my Windows Vista computer
— Reinstalled WMDC 6.0 from the Microsoft Download website.
— Recreated the two relationships from my two devices, and they each did
the initial long sync
— I then tested each device that it could perform a sync not long after it
was reconnected, and they both now sync perfectly. I also tested that making
any changes to some contact details in Outlook 2007 would update the devices
after a sync. and it did.

4/ When using WMDC 6.0, I had to disable the Advanced Networking Functionality on the device, as WMDC was unable to install the correct driver for it when I tried.

4/ This now allowed the TyTn II to sync contacts, calendar and tasks. However, annoyingly, it does not sync the textual content of calendar appointments or tasks – only the headers are synced. This is the ‘partial’ solution that I am having to live with. The good point is that at least contacts are synced properly, and at least with the appointments I will get reminders on the phone plus the title details, which is enough for most of them.

5/ I retried the different versions a number of times but this behaviour was consistent. In the end I had to use system restore to remove 6.1 as the driver update would not remove. It may have done so in safe mode but I did not try this. The behaviour was consistent with both USB and bluetooth syncing.

6/ I also tried syncing with a laptop running Windows XP, but interestingly this also failed to sync, which perhaps points the finger at the TyTn II as this used to work.

7/ I tried running SCANPST.EXE (in the C:\Program Files (x86)\Microsoft Office\Office12 folder) to check for PST corruption as a possible issue. Interestingly it did find a number of issues. It fixed most, if not all of them ( I reran the check again after it had done the fix and some errors remained). However, these errors have not caused any issues when using Outlook and did not allow the TyTn II to sync with WMDC 6.1

It is not clear what the actual issue is, but it is interesting that WMDC 6.0 at least completes a full sync consistently (albeit without calendar/task text). There are any number of posts on the internet complaining about this issue, and I must say I agree with them. It is hugely ironic that an iPhone can sync with Outlook but in many cases a Windows Mobile cannot.

No Comments »

July 7th, 2011
9:52 am
A ui:param/attribute value is passed on invisibly to a called custom tag with attribute of the same name

Posted under JSF
Tags , , , ,

I passed a styleClass attribute to a facelets decorator using <ui:param>. The decorator in turn used a custom tag which had a styleClass attribute.
I discovered whilst looking in Firebug that the styleClass attribute passed to the decorator was being passed on to the custom tag, even though I had not specified a styleClass attribute on the custom tag. The CSS class name was clearly visible in Firebug.

I’ve investigated this with a test application and have confirmed the following points. I have also logged these points under a Mantis issue here.

Note that this was running on Mojarra 2.0.4 FCS, and I am not clear whether all of these issues are by design or would be considered a bug, and how consistent they are across other versions/JSF implementations:-

  1. A ui:param passed say to a decorator is indeed visible via EL in a custom tag called from the decorator. If the custom tag has an attribute of the same name, this will be passed to the tag in preference, but crucially, if the attribute is omitted/defaulted on the tag, the tag will then see the ui:param from the calling decorator.
  2. The above issue in 1/ even occurs if the above decorator is changed to be itself a custom tag, and the ui:param instead becomes an attribute of the parent/calling custom tag. In this case, the nested custom tag sees attributes passed to its parent if the same attribute is not explicitly passed to it.
  3. Fortunately, if a child custom tag is called with an explicit attribute with the same name as an attribute or ui:param passed to its calling tag or decorator, the value in the calling tag/decorator is not modified. This means that you can call child tags without corrupting state in the calling environment.
  4. Point 3/ is also true when a decorator is called with ui:param. If the ui:param has the same name as one used in the caller (either defined there or passed to it), changing the value of the ui:param within the ui:decorate tag to pass it to the decorator does not change the value of the same named parameter outside of the ui:decorate tag.
  5. If a child decorator modifies a ui:param passed by its caller, the modified value is visible only within the child decorator. On return to the calling environment, the ui:param value reverts to what was passed to the child by the caller. This indicates that there is scoping going on.

 

The lessons from this are therefore as follows:-

  1. The prime gotcha here is that if you omit an attribute on a custom tag call or a ui:param on a decorator call, a ui:param or attribute value in the caller’s environment will be visible to the called environment exactly as if it was passed in explicitly! You must therefore take great care to ensure that child calls have explicit empty/null attributes or ui:params specified where there is a name clash with one in the calling environment.
  2. Attribute values and ui:param values are scoped, and you can safely pass the same named ones with different values to child decorators or custom tags without affecting the values in the calling environment. This is even true when defining a ui:param within a ui:decorate tag – it does not affect the value of a similarly named ui:param outside the ui:decorate tag.
  3. Changing the value of a ui:param in a child decorator/tag does not change the value of the same named one in the calling environment. It does however cause the value to change after the point of change in the child environment.

No Comments »

July 6th, 2011
4:28 pm
Issues when using EL expressions in nested Composite Component children

Posted under JSF
Tags , , , ,

There appears to be an issue when using EL in child components included in a composite component using <composite:insertChildren>

I am already using this technique for the tableCC component, to insert the columns as children, and the child columns have plenty of EL in them which is not passed to tableCC, as well as having custom tags as columns. However, there appears to be an issue when this technique is used in nested composite components.

When I tried this, I found that any EL expressions in the child components is evaluated as late as possible in the context of the called composite component, not the caller!

This means that if you need to refer to an attribute passed in to the caller of the CC, you must pass that attribute on to the CC as well as referring to it in the child components, as their EL will be evaluated in the CC not the caller.

Providing you do this, it all works fine. However, the issue with this is that it will tend to break encapsulation of the interface to the child nested CC – you have to change its interface depending on what EL you want to use in the child components passed to it.

This was unacceptable to me, so I switched to a different technique. Instead, my base component (actually a flexible icon/base button using p:commandLink) became a custom tag, and I used facelets <ui:inserts> to handle the insertion of custom markup. I then wrapped composite components around this to provide the necessary custom markup.

The reason for going down this route was that I have had issues with glitchy ajax updates on standard Primefaces buttons at small sizes (see this Mantis issue). Also I was crafting icon buttons with multiple jQuery icons on them, using CSS to position them accurately. This was tricky with a p:commandButton and involved introducing CSS that I was concerned may need change in future releases, so I went my own way when using highly custom buttons and buttons at small sizes.

No Comments »

June 11th, 2011
9:22 am
Cannot disable Java Auto Updates under Windows 7 64bit

Posted under Java
Tags , ,

As I am running a Java development machine I want precise manual control of the versions of Java and all the related tools.

The Java auto updater runs regularly and nags about updating, but I want to turn it off. There is a control panel applet  – “Java (32-bit)” – with an option under the updates tab to do this, however it does not work – if you uncheck the “check for updates automatically” tick box, it appears to save OK but when you close and re-open the applet and look again the value has not changed.

This is due to an apparently long standing Java bug – it does not run with admin privileges and so cannot change the value. It would be nice if it gave an error telling you that it did not work due to a permissions problem, but unfortunately it just fails completely silently.

This post here outlines various solutions to the problem. The accepted answer, which worked for me, is to find javacpl.exe, right click it, and run with admin privileges. The location of it in my case was not where the post suggested, even though I had done a default install, so you will probably need to search for it. In my case I had a couple of versions of it, one was for an old version of Java. The path for mine which I used successfully was C:\Program Files (x86)\Java\jre6\bin

This fixed the problem, and upon reopening the control panel applet (with or without admin privileges) the box was unticked.

No Comments »

March 28th, 2011
11:02 am
Eclipselink error in Eclipse–Schema “null” cannot be resolved….

Posted under JPA
Tags , , ,

This error came up while building a new development environment with the Eclipse Helios SR2 and Eclipselink 2.2.0.
The error appeared for every JPA entity, even after the database drivers/connections were correctly defined.

The simple answer  as detailed here is to right click the project and do a validate – hey presto, all the errors disappear!
This appears to have been around a while and is still not fixed in Eclipselink 2.2.0, but at least it is simple to resolve.

The tip was found on this Oracle tutorial post :-

Note:

If you encounter a Schema “null” cannot be resolved for table “<TABLE_NAME>” error, you’ve hit a known Eclipse bug.
To resolve the issue, right-click the project and choose select Validate from menu. Eclipse will clear the errors.

No Comments »

March 22nd, 2011
8:42 pm
Facelets executes EL expressions in HTML comments by default

Posted under JSF
Tags , , , ,

This one caught me out when I was relying on <!– –> to comment out debug code when developing a facelets page. I found that methods in my Java code were being called seemingly from nowhere!

According to the specification, Facelets should honour (i.e. skip) comments by default, but in my case it did not appear to do so.

This can be enforced by adding the following context parameter to web.xml. Once done, you can safely rely on the use of commenting out when debugging. You can also use ui:remove to tell facelets to ignore sections of markup. This post here gives the details.

Note that the linked post from the above post uses the deprecated parameter name facelets.SKIP_COMMENTS. The correct parameter is as below, as you will be warned about in your server log file if you use the deprecated one!

 

<context-param>
  <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
  <param-value>true</param-value>
</context-param> 

No Comments »

March 22nd, 2011
8:35 pm
JSF rendered attribute calls the getter multiple times

Posted under JSF
Tags , , ,

Initially when I saw this I thought it was a strange bug – the getter for the value expression referenced in a rendered attribute on a JSF2.0 facelets page was called 7 (yes seven) times when I would have expected one call only!

There are logical and historical reasons for this which are detailed in this post here.

The moral of the tale would seem to be that you should not make any assumptions about how often getters for value expressions are called, nor when exactly they are called. If you are doing for example database access you should never do this in a getter, but should use system events (JSF2) or Phase events (JSF1) for the database access as these give fully predictable behaviour as to when the calls happen and give you full control.

No Comments »

March 22nd, 2011
8:11 pm
Fixing Primefaces scrolling table header width issues using jQuery

Posted under JSF
Tags , , , , , , , ,

This has been very much an ongoing chestnut with Primefaces, mainly due to the tricks you have to use in order to get fixed table column headers and a scrolling table. Primefaces does this with a pair of tables – one for the header row and another for the data. The problems which often arise are mismatching columns between the header and the data, incorrectly sized table header above the column headers, and an incorrectly sized header row which does not appear to size properly dynamically when scrollbars are present/absent.

These issues can often be fixed, but it does appear that there is no overall silver bullet which makes everything work in every use case. The best approach I have found is to have a selection of approaches to try, and to apply the appropriate ones to solve problems which arise in particular use cases. The following details the different approaches I have used in various cases to solve width and alignment problems.

The following commented code sample shows how to use jQuery to correct table header width and column header width problems for scrolling tables. These problems are typically triggered by the dynamic appearance/removal of scrollbars, which will depend on table height and row count. Note that the function described, ss_FixTableHeaderWidth, would either be called in an inline script block placed immediately after a table definition in a facelets page (for a static table) or would be triggered as part of an Ajax call (for a dynamically rendered Ajax table). The example shows the static case. Note the following points about the code:-

  • The code may be found in the repository here.
  • The jQuery selectors should be optimised for performance. In general, ID selectors are the most efficient, so  narrow down with an ID selector first if you can (as below). Element selectors are also efficient, but classes can be really slow depending on what the browser supports – jQuery may end up doing a full DOM tree scan for every class selector, which is highly undesirable!. To avoid this below, I have prefixed class selectors with an element type which then makes use of the faster element searching, e.g. div.ui-scrollable-datatable.
  • Avoid duplicating selector searches where possible – in the example below a reuse them where I can, by using previous selector results as the context for subsequent lower level selectors, for example jQuery(‘div.ui-scrollable-datatable-container’, mainDiv) makes use of the jQuery result mainDiv from a previous selector when selecting its descendant scrollable container div.
  • You need to keep track of the difference between DOM elements returned by some calls, and jQuery objects which can be returned by others. You can always wrap a DOM element with a jQuery object using jQuery(element), but this is not always necessary. Avoid the overhead of doing it when you already have a jQuery object as it is redundant. The jQuery documentation makes all this clear.
  • The jQuery online docs are available here.  You cannot directly download the docs from the jQuery site, but it does link to some unofficial PDF downloads. However, the best and most searchable option seems to be an unofficial windows help file/CHM version download linked from StackOverflow (not fully up to date but still very useful). This is available here.
  • The RH header column size is set to auto to accommodate header row size changes, the idea being that this RH column will expand to fill the row, and the browser will not mess with other column sizes. Note that the column widths are just a guide to the browser and it is free to mess with them. This can be really awkward as we rely on the header table and data table being rendered exactly the same way to line up. This auto approach seems to work.
  • Firefox (3.6 and 4) has a problem whereby when setting an element width (in this case with jQuery), the actual value set is often 1px less than the requested value (particularly a problem when setting header table width). This can easily be seen by reading back the element width immediately after setting it. The fix I use for this is to do all width setting in a function (ss_setWidth) which checks the width afterwards and calculates the value of the mismatch. If there is a mismatch, the mismatch is then added to the width to set, and the element width is set a second time. This function is safe to use for all browsers.

 

Function definition, placed in page header section

    <script type=”text/javascript”>
    //<![CDATA[

        function ss_FixTableHeaderWidth(formId, tableId) {
           
            /*
             *Fix incorrect table header width due to scrollbars
             */
           
            var fullTableId = ‘#’ + formId + ‘\\3A’ + tableId;
            var topHeader = jQuery(fullTableId + ‘ > div.ui-datatable-header’);
            var mainDiv = jQuery(fullTableId + ‘ > div.ui-scrollable-datatable’);
            var headerTable = jQuery(‘table.ui-scrollable-datatable-header’, mainDiv);
            var dataContainer = jQuery(‘div.ui-scrollable-datatable-container’, mainDiv);           
            var dataTable = jQuery(‘table.ui-scrollable-datatable-body’, dataContainer);           
            var lastColumnHeader = jQuery(‘thead > tr:eq(0) > th:last’, headerTable);

/*           
            alert (‘TableId=’+fullTableId + ‘\n’ +
                   ‘topHeader=’+topHeader.attr(‘class’) + ‘\n’ +
                   ‘mainDiv=’+mainDiv.attr(‘class’) + ‘\n’ +
                   ‘headerTable=’+headerTable.attr(‘class’) + ‘\n’ +
                   ‘dataContainer=’+dataContainer.attr(‘class’) + ‘\n’ +
                   ‘dataTable=’+dataTable.attr(‘class’) + ‘\n’ +
                   ‘lastColumnHeader=’+topHeader.attr(‘class’));
*/           
            /*
             * Set the RH header column width to auto to prevent header table width adjustments
             *  from messing up column alignments
             */
            lastColumnHeader.css(‘width’, ‘auto’);

            /*
             * For some themes (pepper-grinder, overcast, ui-lightness), the width is incorrectly set for a scroll bar
             * even when there isn’t one. Detect whether scroll bars are actually present and fix the width if required.
             */
            if (dataContainer.outerHeight() >= dataContainer.get(0).scrollHeight) {
                //alert(‘Scroll bars not present’);
                //dataContainer.width(dataTable.outerWidth());
                ss_setWidth(dataContainer, dataTable.outerWidth());
            }       

            //Now set the width of the column headers table correctly and then finally the table header to match.
            var newHeaderTableWidth = headerTable.width() + dataContainer.outerWidth() – headerTable.outerWidth();
            var newTopHeaderWidth = topHeader.width() + dataContainer.outerWidth() – topHeader.outerWidth();

            //headerTable.width(newHeaderTableWidth);
            ss_setWidth(headerTable, newHeaderTableWidth);
            //topHeader.width(newTopHeaderWidth);
            ss_setWidth(topHeader, newTopHeaderWidth);
        }
       
        function ss_setWidth(element, value) {
           /*
            * This function overcomes an issue with Firefox (3.6 and 4), whereby the actual width set for an element
            * (particularly the header table) is sometimes less (typically 1px less) than the passed width to be set.
            * We read back the width after setting it, and if it differs from what we set,
            * we adjust our original value by the mismatch and set the width again.
            */           
            element.width(value);
            mismatch = value – element.width();
            if (mismatch != 0) {
                //alert(‘mismatch=’+mismatch+’ fixed’)
                element.width(value + mismatch);
            }
        }       
    //]]>
    </script>

Function call, placed inline immediately following table

<p:dataTable …>

</p:dataTable>
<script type=”text/javascript”>ss_FixTableHeaderWidth(‘frmTest’, ‘tblTable’);</script>

Iterating columns to set the width for each one individually

The following code sample uses the jQuery .each loop to iterate the header columns and set the width of each one to its matching data column (along with setting the table/row widths correctly). This sounds ideal for solving the header problems, but in practice it did not work well. The main issue is that jQuery reported a different value for the header column widths to that reported by the browser (via Firebug). The values were out by 1px, which caused an incremental mismatch in the column alignment as you go left to right. This approach was therefore abandoned in favour of just setting the RH header column size to auto to accommodate row size changes, as explained above. However, I reproduce the code here as it is a useful example of how to iterate a returned  jQuery object collection from a selector.

Function definition, column iteration version

    <script type=”text/javascript”>
    //<![CDATA[

        function ss_FixTableHeaderWidth(formId, tableId) {

            /*
             *Fix incorrect table header width due to scrollbars
             */
            
            var fullTableId = ‘#’ + formId + ‘\\3A’ + tableId;
            var topHeader = jQuery(fullTableId + ‘ > div.ui-datatable-header’);
            var mainDiv = jQuery(fullTableId + ‘ > div.ui-scrollable-datatable’);
            var headerTable = jQuery(‘table.ui-scrollable-datatable-header’, mainDiv);
            var dataContainer = jQuery(‘div.ui-scrollable-datatable-container’, mainDiv);           
            var dataTable = jQuery(‘table.ui-scrollable-datatable-body’, dataContainer);           
           
            /*
             * For some themes (pepper-grinder, overcast, ui-lightness), the width is incorrectly set for a scroll bar
             * even when there isn’t one. Detect whether scroll bars are actually present and fix the width if required.
             */
            if (dataContainer.outerHeight() >= dataContainer.get(0).scrollHeight) {
                //alert(‘Scroll bars not present’);
                //dataContainer.width(dataTable.outerWidth());
                ss_setWidth(dataContainer, dataTable.outerWidth());
            }                       

            /*
             * Now iterate the columns with a jQuery each loop and set the header column width
             * to be the same as its corresponding data column width.
             * This is for illustration – the idea has been abandoned, as I found that Javascript/jQuery
             * reports a different value for the header widths to firebug on the final rendered page (out by 1px).
             * This causes an increasing mismatch between data columns and header columns as you go from left to right.
             * The column widths are only a suggestion and the browser may modify them anyway.
             * Therefore the final version, in SortTable.xhtml just sets the RH column width to auto
             * to take up the slack when the row width is changed, and leaves the others alone.
             * This appears to work much better.
             * However the iteration technique here is a useful working jQuery example.
             */
            var columnHeaders = jQuery(‘thead > tr:eq(0) > th’, headerTable);
            var firstRowCells = jQuery(‘tbody > tr:eq(0) > td’, dataTable);
            var columnCount = columnHeaders.size()
           
            columnHeaders.each(function(idx){
                    var columnHeader = jQuery(this);
                    if (idx < columnCount – 1) {
                       
                        var firstRowCell = jQuery(firstRowCells.get(idx));
/*
                        alert(‘idx=’+idx+’\n’+
                              ‘header width=’+columnHeader.width()+’\n’ +
                              ‘header csswidth=’+columnHeader.css(‘width’)+’\n’ +
                              ‘header innerWidth=’+columnHeader.innerWidth()+’\n’ +
                              ‘header outerWidth=’+columnHeader.outerWidth()+’\n’ +
                              ‘data width=’+firstRowCell.width()+’\n’ +
                              ‘data csswidth=’+firstRowCell.css(‘width’)+’\n’ +
                              ‘data innerWidth=’+firstRowCell.innerWidth()+’\n’ +
                              ‘data outerWidth=’+firstRowCell.outerWidth());
*/
                        var newWidth = columnHeader.width() + firstRowCell.outerWidth() – columnHeader.outerWidth();
                        //alert(‘idx=’+idx+’,width=’+columnHeader.width()+’, newWidth=’+newWidth);
                        //columnHeader.width(newWidth);
                        ss_setWidth(columnHeader, newWidth);
                    }
                    else {
                        columnHeader.css(‘width’, ‘auto’);
                    }
              });

            //Now set the width of the column headers table correctly and then finally the table header to match.
            var newHeaderTableWidth = headerTable.width() + dataContainer.outerWidth() – headerTable.outerWidth();
            var newTopHeaderWidth = topHeader.width() + dataContainer.outerWidth() – topHeader.outerWidth();

            //headerTable.width(newHeaderTableWidth);
            ss_setWidth(headerTable, newHeaderTableWidth);

            //topHeader.width(newTopHeaderWidth);
            ss_setWidth(topHeader, newTopHeaderWidth);
        }
       
        function ss_setWidth(element, value) {
            /*
             * This function overcomes an issue with Firefox (3.6 and 4), whereby the actual width set for an element
             * (particularly the header table) is sometimes less (typically 1px less) than the passed width to be set.
             * We read back the width after setting it, and if it differs from what we set,
             * we adjust our original value by the mismatch and set the width again.
             */                       
            element.width(value);
            mismatch = value – element.width();
            if (mismatch != 0) {
                //alert(‘mismatch=’+mismatch+’ fixed’)
                element.width(value + mismatch);
            }
        }       
    //]]>
    </script>

No Comments »

March 9th, 2011
12:49 pm
Problems updating a checkbox in a Primefaces Table header

Posted under JSF
Tags , , , ,

With reference to my previous post, I found that a checkbox in a row cell in a Primefaces Table could not (from its value change listener) update a checkbox in the header. Per the previous post I was using component binding and calling UIInput.setValue() to update the value.

Strangely, another checkbox (checkbox B) outside the table was able to (again from its value change listener) update the checkbox in the table header.

More strangely, I then just moved checkbox B into a table row cell, and then found that it would not update the header checkbox.

I noticed that the checkbox row selection feature in the Primefaces showcase has the same issue – if you select all via the checkbox in the header, then all the rows become correctly selected. If however you then deselect a row, you would expect the header check box to deselect itself – however it does not.

As a further test, I tried it with Ajax, and was still unable to update the header checkbox from a row checkbox listener.

This Primefaces forum post may points to some possible causes, but its not clear cut. It certainly appears to be an internal issue to do with the Primefaces Table.

Workaround

One workaround to this would be to link the checkboxes client side with Javascript or jQuery. I resisted this because I will need to perform immediate actions elsewhere on the form based on a select click, so originally decided to do it all server side with listeners and (in the final solution) Ajax. However I may end up doing both – doing the at least some of linked selecting client side, but still using server side listeners for the other requirements.

Doubtless I will need to be careful that my own Javascript/jQuery does not interact negatively with the Ajax Javascript when implementing this. This post here points out that programmatic update of components via javascript does not fire events – only user actions cause events. In my case this need not be an issue – I could used javascript to cause row check box clicks to update the header check box. For example, if all rows were selected manually, I would tick the header box via script. Similarly, if then a row was deselected, I would untick the header check box. In each of those cases, I would not want or need any events to fire due to the header check box change. However, if the user explicitly clicked the header check box either way, I could use its listener to update all the row boxes (as I know this works) and to take any other action needed. whether in this latter case I allow the Javascript to update all the row boxes or not I am not sure – it is more consistent as then all the interlocking is in Javascript, but it will not cause row checkbox events to fire, so the header checkbox listener will still need to update all the selected properties for each row checkbox. If Javascript updates all the row boxes, then at least I don’t need to do any re-render of them which is more efficient. However, it is more complex as it involves iterating all the rows in script, although I expect this can be done pretty easily via jQuery.

No Comments »