Setting Multi-Select Widths in a SharePoint EditForm.aspx Using JavaScript

<UPDATE date=”2009-01-25″>
I now have a function in my jQuery Library for SharePoint Web Services called SPSetMultiSelectSizes which accomplishes this in a more robust way, taking into account the font, font size, etc.
</UPDATE>

When you have a multi-select lookup column in a list, SharePoint provides you with a control that shows two select boxes next to each other on EditForm.aspx.  There are two buttons (‘Add >’ and ‘< Remove’) that let you move values between the two, selecting or deselecting the values.

By default, the select boxes are a fixed width and, in many cases, not wide enough to let your users see the values very well.  The following JavaScript will set the widths of the select boxes based on the length of the longest value available in the lookup.  It isn’t fully multipurpose, as I wrote it for a specific instance with a particular set of branding (font size, spacing, etc.) but it ought to give you a very good start to use it yourself.  (With the fonts that I was using, I found that 7 times the number of characters in the longest value worked well to calculate the right width.  You’ll probably need to experiment.)  Pass in the name of the column you want to adjust.

// setSelectWidth: Set the width of a lookup column's select box based on the values it contains
// Arguments:
// columnName: The name of the column which is being displayed in the select box
//
function setSelectWidth(columnName) {

  var charFactor = 7; // Approximate pixels per character

  // Left side
  leftColumnSelect = getTagFromIdentifierAndTitle("select","",columnName + " possible values");
  if(leftColumnSelect != null) {
       leftColumnSelectDIV = findParentElement(leftColumnSelect, "DIV");
  }

  // Right side
  rightColumnSelect = getTagFromIdentifierAndTitle("select","",columnName + " selected values");
  rightColumnSelectDIV = findParentElement(rightColumnSelect, "DIV");

  // Find the longest value
  var longestValue = 0;
  for (var i=0; i  leftColumnSelect.options.length; i++) {
    if(leftColumnSelect.options[i].text.length > longestValue) {
      longestValue = leftColumnSelect.options[i].text.length;
    }
  }
  for (var i=0; i < rightColumnSelect.options.length; i++) {
    if(rightColumnSelect.options[i].text.length > longestValue) {
      longestValue = rightColumnSelect.options[i].text.length;
    }
  }

   // Set the widths of the two selects and their containing DIVs
   var newWidth = charFactor * longestValue;
   leftColumnSelectDIV.style.width = newWidth;
   leftColumnSelect.style.width = newWidth;
   rightColumnSelectDIV.style.width = newWidth;
   rightColumnSelect.style.width = newWidth;
}

This function builds on the getTagFromIdentifierAndTitle function provided in an excellent blog post I’ve referenced before over at the Microsoft SharePoint Designer Team Blog.  I’ve also created a findParentElement function you’ll see called above, which finds a specific parent element for a tag.  The code for this is below:

// findParentElement: Find an object's specified parent element
// Arguments:
// thisElement: The element you want to search from
// parentTag: The parent tag you want to find
//

function findParentElement(thisElement, parentTag) {
  var currentElement = thisElement;

  while(currentElement.tagName != parentTag) {
    currentElement = currentElement.parentNode;

    //alert(currentElement.tagName);
    if(currentElement.tagName == parentTag) {
      //alert('HIT:' + currentElement.tagName);
      return currentElement;
    }
  }
  return null;
}

31 Comments

  1. Hi Marc, Please can you send a file example EditForm.aspx ?? ..the lookup Column name is a “Formulários”. You know if this ‘á’ encodes ? i sent another question in ur blog. Thanks a lot.

    Reply
  2. Marc,
    What am I missing here? I have posted this in my CEWP.

    $(document).ready(function() {
      $().SPServices.SPSetMultiSelectSizes({
        multiSelectColumn: “Application Impacts – check all that apply”,
      });
    });
    

    And this is not working. any help would be greatly appreciated. thanks.

    Reply
    • Meghan:

      Do you have the jQuery and SPServices files somewhere with references to them? To test your references, add an alert inside the $(document).ready():

      $(document).ready(function() {
        alert("jQuery is loaded!");
        $().SPServices.SPSetMultiSelectSizes({
          multiSelectColumn: “Application Impacts – check all that apply”,
        });
      });
      

      M.

      Reply
      • Yes. I have referenced them like this.

        <script type="text/javascript" src="OCM/Code/EnlargeMultiSelect/jquery-1.4.2.min.js"></script>
        <script type="text/javascript" src="/OCM/Code/EnlargeMultiSelect/jquery.SPServices-0.5.8.js"></script>
        <script type="text/javascript" src="/OCM/Code/EnlargeMultiSelect/jquery.SPServices-0.5.8.min.js"></script>
         
        $(document).ready(function() {
        alert("jQuery is loaded!");  
          $().SPServices.SPSetMultiSelectSizes({
            multiSelectColumn: "Application Impacts - check all that apply",
          });
          // You can include other script which you want to run at page load in this block as well
        });
        

        Let me now if this is not right

        Reply
        • Well, odds are that one of your references isn’t right because you have a leading slash on the SPServices one and not on jQuery. You should also only be using either the regular or minified version of SPServices, not both. Also, remove the comma after “Application Impacts – check all that apply”, *and* you need to wrap your script in a script tag. [I added a couple of those fixes based on an email exchange with Meghan.]

          <script type="text/javascript" src="/OCM/Code/EnlargeMultiSelect/jquery-1.4.2.min.js"></script> 
          <script type="text/javascript" src="/OCM/Code/EnlargeMultiSelect/jquery.SPServices-0.5.8.min.js"></script> 
          <script type="text/javascript"> 
          $(document).ready(function() {
            alert("jQuery is loaded!");  
            $().SPServices.SPSetMultiSelectSizes({
              multiSelectColumn: "Application Impacts - check all that apply"
            });
            // You can include other script which you want to run at page load in this block as well
          });
          </script>
          

          M.

          Reply
  3. Hello Marc,

    Thank you very much for providing this information. I have been looking for a solution to this headache for some time. However, Now that I have the aspirin, I cannot seem to open the bottle…

    How do I add your jQuery to my form? Typically, I use a CEWP however, when I copy your syntax above and place it in there, nothing happens. I must be missing something and considering I am new to jQuery I am willing to bet I am missing the opening and closing tags of

    Also, I would love to try the other option you are providing (Calling the SPServices.SPSetMultiSelectSizes) but this also escapes my realm of knowledge.

    Any assistance that you can provide would be GREATLY appreciated.

    Thank you again,
    B

    Reply
      • Marc,

        Thank you for the reply, I was able to finally make this work. It turns out the issue was the lack of having the jquery Library registered as well. I just had your SPServices items loaded.

        Follow-up question, The SPCascadeDropdowns options, can that be used in SharePoint 2007? we have plans to migrate to 2010 next year, however, I still would like to create some other “Functional” forms within our current site.

        Thank you again for all of your help… It appears I will be going out to purchase a jquery book now to use :-) Always like to read new material.

        B

        Reply
  4. Thank you again for the fast response. I have provided you the recognition you justly deserve for helping me out here. Now if I can just figure out the second part of the originally posted question here

    Thank you again Marc,
    Bryan

    Reply

Have a thought or opinion?