Fixing the Width of a Select 2 with a Long Value in a Bootstrap Form Group or Input Group

If you have a Select2 control within a form-group or input-group div in a Bootstrap UI, a long value can cause the Select2 to grow to become wider than its container. In this post, I’ll show how to fix the issue.

The Problem with Large Values

In this demo, I have a form with two columns of fields, each within a well (which makes the container size very clear).

Select2 Long Values - A

In one field, there is a very long value. This usually isn’t an issue when you have explicit control over the options, but if you have an application where a drop-down box’s choices come from a plain text field on other documents, it’s possible.

Select2 Long Values - B

When I select the long value, it limits the amount of text displayed in the box to what will fit on one line, but it expands the size of the Select2 outside of its container.

Select2 Long Values - C

If I remove the second column of fields and re-test, it looks like the Select2 was enlarged to be the same the size as the parent container, which is too big for the area that it’s supposed to be in.

Select2 Long Values - C2

Fixing with CSS

This is a known issue with Select2 inside of a form-group or input-group within Bootstrap.

Fortunately, there’s a simple CSS fix, adapted from this post on github

.form-group .select2-container {
  position: relative;
  z-index: 2;
  float: left;
  width: 100%;
  margin-bottom: 0;
  display: table;
  table-layout: fixed;

If you’re using an input-group instead of a form-group, then change the first line to this:

.input-group .select2-container {

Select2 Long Values - D

Fixing a Bug with Dropdown Buttons in 9.0.1 FP3 and FP4

If you use Dropdown Buttons in XPages on Domino 9.0.1 and a OneUI 2.x theme, there’s a bug with two recent fixpacks (FP3 and FP4) that breaks them. In this post, I’ll show what happens and share code I’ve used to fix them.

Version Disclaimer

The configuration where I’ve seen this is a test server with Domino 9.0.1 and extension library version 9.0.1.v00_02_20131212-1115. I have not set up other configurations (such as new extension libraries or a non-extension library server) and tested them at this point.

Extension Library Fix

Note: The latest relase of the extension library (Aug 31, 2015) says that it includes a fix for this issue. SPR PEDS9ZKCZU – Fix dropdown button regresssion in OneUI 2.X

Dropdown Button Issue

The dropdown button control should generally look like this when clicked:


However, an issue was introduced with 9.0.1 FP3 (and continued with FP4) that caused it to be generated as a link instead.


The good news is that it still works.

Generated Source

Inspecting the source of the button in both versions, it’s clear to see the difference. The original version generates a button tag.

<div id="view:_id1:dropDownButton1" class="lotusBtnContainer">
  <button aria-owns="view:_id1:dropDownButton1_ab_0_mn" aria-haspopup="true" role="button" id="view:_id1:dropDownButton1_ab_0" class="lotusBtn">
    Update Status 
    <img src="/oneuiv2/images/btnDropDown2.png" aria-label="Show Menu" alt="Show Menu">
    <span class="lotusAltText">

The version in FP3 and FP4 generates a link.

<div id="view:_id1:dropDownButton2" class="lotusBtnContainer">
    <span aria-owns="view:_id1:dropDownButton1_ab_0_mn" aria-haspopup="true" role="button">
      <a id="view:_id1:dropDownButton1_ab_0" href="javascript:;" class="lotusBtn">
        Update Status 
        <img src="/oneuiv2/images/btnDropDown2.png" aria-label="Show Menu" alt="Show Menu">
        <span class="lotusAltText">

In both cases, the same JavaScript is generated in a script tag at the end of the page

function view__id1_dropDownButton1_ab_0_mn_ctor(){
var m=new dijit.Menu({"title":"Drop Down Menu"});
var ch0=(new dijit.MenuItem({label:"Draft",onClick:function(){XSP.setSubmitValue("Draft");XSP.fireEvent(arguments[0], "view:_id1:_id4", "view:_id1:dropDownButton1", null, true, 2, null);}}));
var ch1=(new dijit.MenuItem({label:"Submitted",onClick:function(){XSP.setSubmitValue("Submitted");XSP.fireEvent(arguments[0], "view:_id1:_id4", "view:_id1:dropDownButton1", null, true, 2, null);}}));
var ch2=(new dijit.MenuItem({label:"Approved",onClick:function(){XSP.setSubmitValue("Approved");XSP.fireEvent(arguments[0], "view:_id1:_id4", "view:_id1:dropDownButton1", null, true, 2, null);}}));
var ch3=(new dijit.MenuItem({label:"Rejected",onClick:function(){XSP.setSubmitValue("Rejected");XSP.fireEvent(arguments[0], "view:_id1:_id4", "view:_id1:dropDownButton1", null, true, 2, null);}}));
var ch4=(new dijit.MenuItem({label:"Cancelled",onClick:function(){XSP.setSubmitValue("Cancelled");XSP.fireEvent(arguments[0], "view:_id1:_id4", "view:_id1:dropDownButton1", null, true, 2, null);}}));
return m;

The Fix

To fix it, I wrote a JavaScript function that takes the generated output and changes it back to the original output. It also re-attaches the event handling functions to each menu option. I added the function to a client-side JavaScript library on the page and then called it with the client-side ID of a drop-down button control to fix it.

Note: Testing has been limited, but there are no known issues at this time. Please test thorougly before putting into a production environment.

Here’s the library function:

function fixDropDownButtons(clientID) {
  try {
  var dropdownDiv = dojo.byId(clientID);
  var html = dropdownDiv.innerHTML;
  // Remove opening and both closing span tags
  html = html.substring(13, html.length-16);
  // Get the attributes from the next span tag (parse from after <span to the next left angle bracket -1
  var idx = html.indexOf('>');
  var attributes = html.substr(0, idx);

  // Add the attributes to the next tag
  html = html.substr(idx + 4);
  html = '<button ' + attributes + ' ' + html;

  // Remove the href="javascript:;" attribute
  idx = html.indexOf('href=');
  // NOTE: in IE11, the href="javascript:;" attribute is the last attribute, so it goes up to the '>'
  // In Firefox, it's not the last attribute, so it can be located by the next space
  // Solution: Find the next space and the next closing bracket and use the lower of the two numbers
  var idxSpace = html.indexOf(' ', idx+1) + 1;
  var idxBracket = html.indexOf('>', idx+1);
  var idx2 = idxSpace < idxBracket ? idxSpace : idxBracket;
  html = html.substr(0, idx) + html.substr(idx2);
  html = html.replace('</a>', '</button>');;
  dropdownDiv.innerHTML = html;
  // Re-connect the event handler that the server already generated.
  // This assumes that it's part of the global window object
  var clientID_noColon = clientID.replace(/:/g, '_');
  dojo.connect(dojo.byId(clientID + "_ab_0"),"onclick",function(thisEvent) {
    XSP.openMenu(thisEvent,eval(clientID_noColon + "_ab_0_mn_ctor"));
  } catch (e) {
    console.warn('Error in fixDropDownButtons(' + clientID + ') - ' + e.toString());    


It’s largely text parsing and rearranging once it gets the HTML generated for the component. (Read code comments for more details.)

Toward the end, it re-connects event handlers for the dropdown button options. Fortunately, there’s a predicatable naming pattern, so it can consistently determine how to find the correct functions to re-attach.

The code also accounts for the fact that the HTML attributes are generated in differnet ordres in different browsers, which affects the text parsing.

Calling the Function

Here’s how to call it from the onClientLoad event of the page:


This code uses pass-thru logic to determine the button’s client-side JavaScript ID and passes it to the function.

Potential Improvements

This is my initial solution, but there are a few ways that it could be quickly enhanced.

First of all, it could be enhanced to work based on a class or just automatically finding drop-down buttons rather than having to determine the client-side ID and pass it to the function.

It could also be updated to only fix buttons as needed, in order to prevent it from causing problems when you update to a fixpack or extension library version that solves the original bug. A simple check for whether it has a button tag could determine this.

XPages Tip: Reading Custom Properties and Modifying a Component Before a Page Loads

If you need to read a property on a custom control and do something to any component on the page before a page loads, it can get tricky because the compositeData object is not available in the beforeRenderResponse event and getComponent() does not work in the beforePageLoad event.

I have an application where I need to dynamically inject components before a page loads. However, the injection depends on custom properties on a custom control, so it needs to read the properties and then get a handle to a component and modify it. Since the compositeData object isn’t available in the beforeRenderResponse event and getComponent() doesn’t work in the beforePageLoad event, there’s no single place to put the code that I need.

Fortunately, there’s a simple workaround. Code in the beforePageLoad event can read custom properties from the compositeData object and store them in viewScope variables. Then, code in the beforeRenderResponse event can read those values from viewScope and use getComponent() to get the handle to the component that I need to modify.

MWLUG Slides – AD114 Take Your XPages Development to the Next Level

In this session at MWLUG 2015, Paul Calhoun and I dug into a number of features already available in XPages, but not as widely used.

We only had time to cover half of the sections, but the full set of slides is available here

Topics include:

  1. Application Responsiveness (primarily JSON RPC)
  2. SSJS Tips
  3. Modifying Component output
  4. Java Tips
  5. Custom Controls (including dynamic field binding to make reusable fields)
  6. Resources for learning more
  7. Debugging Tips
  8. Event handlers
  9. Dojo

Updating Select2 Styling to Match Bootstrap Fields

Select2 is an awesome jQuery plugin to enhance the functionality of combo boxes. But if you implement it in an application with a Bootstrap UI, you’ll notice that the styling is not consistent. In this post, I’ll show how to make the styling of Select2 fields consistent with other fields on the form.

Bootstrap Default Styling

Here’s an example of a simple Bootstrap form, including two combo box fields. The styling is very consistent across all of the fields.

Select2 A - Default Drop-Down

Select2 Default Styling

Once I implement Select2 and add the code to initialize combo boxes as Select2 fields, they styling changes. The width and internal padding and line spacing are not consistent with other bootstrap fields. (Click image to enlarge in order to see the difference more clearly.)

Select2 B - Default Select2 Style

Consistent Styling

Fortunately, by inspecting a standard bootstrap field either in the bootstrap CSS or in the browser’s developer tools, I can see the styles in use and replicate them for a more consistent look.

Select2 C - Consistent Select2 Style

Here is the CSS required to make it happen:

.select2-container {

.select2-container a.select2-choice {
  font-size: 14px;
  height: 38px;
  padding: 8px 12px;
  line-height: 1.42857;

.select2-container .select2-choice .select2-arrow {

The first rule makes the field width use 100% of the size of its container, as bootstrap fields do.

The second set of rules sets the font and field styling to make them consistent.

The third rule vertically centers the drop-down arrow for the larger field.

Fixing an Issue with Glyphicons with a Bootswatch Theme in XPages

In this post, I’ll describe an issue that I had with glyphicons when using a Bootswatch theme in XPages and how to fix it.

When you use a Bootswatch theme, you do not need to separately include the original
bootstrap.css file. In fact, it would be inefficient to do so, because the styling is provided by the Bootswatch CSS file.

When adding any additional Javascript libraries or CSS to an XPages application, I generally put them in their own folder under WebContent and then include the library or stylesheet via the application theme.


However, I noticed an issue when doing this recently. The Bootswatch theme styling loaded fine, but glyphicons on the page were
not displayed properly; the unrecognized font character symbol was displayed instead.

Glyphicons are loaded as a font (much like Font Awesome), so I looked through the stylesheet to see how the font was included. As you can see, the reference is relative to the current directory, assuming a standard Bootstrap directory structure.

@font-face {
  font-family: 'Glyphicons Halflings';
  src: url('../fonts/glyphicons-halflings-regular.eot');
  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');

There are two ways to go about fixing this:

  1. You can update the font references to be relative to the actual directory structure.
  2. Much more simply, you can move the bootswatch CSS file into the css directory under the bootstrap directory so the relative font file references work without being modified.

XPages Tip: Displaying View Panel Sort Icons on a Separate Line

If there isn’t enough room to display both the column title and sort icons in all column headers in a view panel, you can end up with an uneven look. In this post, I’ll show how to use CSS to move the sort icons down to a new line.

Column Header Layout

If you’re using a view panel with sortable columns, you will ideally not have too many columns and instead have enough screen real estate that the sort icons don’t make a difference.

View Panel Sort Icons - 1

However, a common scenario is that there are a lot more columns crammed in and some (but not all) sort icons wrap to a new line. This ends up causing an uneven look.

View Panel Sort Icons - 2

In addition, the icons take up space, so you may have columns that have a 1- or 2-letter code, but the sort icon makes the column 2-3 times wider than it needs to be, so you lose precious real estate.

If that happens and you’d like to make them consistent, you can use CSS to always move the sort icons to the next line.

Column Header Source

In order to apply CSS to adjust the layout, we need to view the page source to see what’s being generated.

This snippet contains the tags that start the view panel (line 1), start the column header row (lines 2-3), and display the first column header (lines 4-16).

<table id="view:_id1:viewPanel1" class="xspDataTable">
      <th scope="col">
        <div class="xspPanelViewColumnHeader">
            <a id="view:_id1:viewPanel1:viewColumn1:__internal_header_title_id" href="#" class="xspPanelViewColumnHeader">
              <span class="xspPanelViewColumnHeader">Group</span>
            <img id="view:_id1:viewPanel1:viewColumn1:__internal_header_sort_icon" src="/domjava/xsp/theme/common/images/sort_none.gif" 
alt="Sort Toggle" title="Sort Toggle" class="xspImageViewColumnHeaderSort">

This shows that a column header div contains a span with the column title and another span with the sort icon.

Adding a New Line with CSS

This gives us enough information to know how to target the proper element with CSS. There are several ways to go about it. My example will target the table (with class name), div (with class name), and then get the first span tag. It will add the new line after the first span.

table.xspDataTable div.xspPanelViewColumnHeader span:first-of-type:after {
  content: '\A';
  white-space: pre;

The '\A' in the content attribute denotes a new line with CSS. It does not work to put a <br> tag there. The white-space attribute is also required or you may not see any difference.

Now, all of the sort icons appear on a separate line.

View Panel Sort Icons - 3

You can tweak it by adjusting the space between the lines or centering, etc, but this gets the ball rolling.

Also, if you want to modify the images themselves, you can target .xspImageViewColumnHeaderSort with CSS.


Get every new post delivered to your Inbox.

Join 78 other followers