Control the width of SPSetMultiSelectSizes

Feb 18, 2010 at 3:26 PM

I have a list which I use the SPCascadeDropdowns to very good effect. I have a field "Predecessors" that is dependent on the content of the "Project" field.

When the new form is displayed, "Project" is empty, and therefore the Predecessors multi-select field is empty too. This makes the bottom scroll bar disabled. When a Project is selected, the Predecessors field gets populated, but the bottom scroll bar remains disabled. I have been able to add the SPSetMultiSelectSizes function to the "completefunc" property, and the multi-select field now sizes itself to the content of the field. However, because the multi-select field starts empty, the SPSetMultiSelectSizes function makes the left and right select boxes in the field very narrow.

Would it be possible to extend this function to have a minWidth and a MaxWidth property (pixels)? If the text is longer than MaxWidth, then the bottom scroll bar should be enabled. If the text is shorter than minWidth, then the bottom scroll bar can be disabled.

[goes away, scratches his head, thinks for a bit, tries some code changes out, and then comes back to this post...]

I have written the JavaScript changes for the function, but need to add the properties (I'm not sure how to use the extend() function). The following code has hard-coded minWidth of 100px and maxWidth of 200px. I modified the jquery.SPServices-0.5.1.js and it worked. Below is an extract from this file, my new code marked in bold.

  // We'll add 5px for a little padding on the right.
  var divWidth = $("#" + cloneId).width() + 5;
  var newDivWidth = divWidth;
  if(divWidth < 100) divWidth = 100;
  if(newDivWidth < 100) newDivWidth = 100;
  if(newDivWidth > 200) newDivWidth = 200;
  // Subtract 17 from divWidth to allow for the scrollbar for the select 
  var selectWidth = divWidth - 17;
 
  // Set the new widths
  possibleValues.css("width", selectWidth + "px").parent().css("width", newDivWidth + "px");
  selectedValues.css("width", selectWidth + "px").parent().css("width", newDivWidth + "px");

The result: then the new form is shown, the multi-select is 100px wide and empty. When the Project is selected, the values are filled in, and they scroll left/right (and is shown 200px wide). When a Project is selected which shows no values in the Predecessor multi-select, it is shown 100px. When a Project is selected which shows short values in the Predecessor multi-select, it is shown 100px.

Hope that's helpful and that the parameters / properties can be added easily...

Alex

Feb 18, 2010 at 3:38 PM

OK, changing the properties / parameters was pretty easy ;)

The options bit is now:

  var opt = $.extend({}, {
   multiSelectColumn: "",
   useMinMax: false,
   minWidth: 100,
   maxWidth: 200
  }, options);

And the code I changed earlier is now modified to:

  // We'll add 5px for a little padding on the right.
  var divWidth = $("#" + cloneId).width() + 5;
  var newDivWidth = divWidth;
  if(opt.useMinMax == true)
  {
    if(divWidth < opt.minWidth) divWidth = opt.minWidth;
    if(newDivWidth < opt.minWidth) newDivWidth = opt.minWidth;
    if(newDivWidth > opt.maxWidth) newDivWidth = opt.maxWidth;
  }
  // Subtract 17 from divWidth to allow for the scrollbar for the select
  var selectWidth = divWidth - 17;
 
  // Set the new widths
  possibleValues.css("width", selectWidth + "px").parent().css("width", newDivWidth + "px");
  selectedValues.css("width", selectWidth + "px").parent().css("width", newDivWidth + "px");

I think I'm beginning to get the hang of this...!

Alex

Coordinator
Feb 18, 2010 at 3:41 PM

Alex,

Marc is on vacation, but I'll offer some insight. How are you calling the SPCascadeDropdowns function, are you using it inside $(document).ready? If so, if the SPSetMultiSelectSizes function is called first, before anything else, it should size the multi-selects for any possible value, before they get filtered down by SPCascadeDropdowns.

That said, I believe Marc and I had a casual discussion at some point about how it'd be nice to be able to specify a width (overriding the auto-sizing), and your min/max suggestion is along that line. Ideally it'd become 3 optional parameters, min, max and width, with the latter overriding the auto part of the function. I'll post this as a work item, but I don't believe it'll get worked until Marc gets back from vacation--the library is his baby so I'll let him decide how/if he wants to implement the changes.

Mike

Coordinator
Feb 18, 2010 at 3:42 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Feb 18, 2010 at 3:52 PM

Thanks Mike.

Yes, the call to SPCascadeDropdowns is indeed inside $(document).ready. The completefunc must be being called because the Parent column ("Project" in my case) contains a value - it's a required field, so doesn't have "(none)" at the top.

In my second post, where I'd added the options bit, there are 3:
useMinMax: false - default behaviour is the original behaviour. Set to true to use the next two parameters
minWidth: 100 - default is 100px but can override with own value
maxWidth: 200 - default is 200px but can override with own value

Anyway, it's working a treat for me, so I'm happy. I changed the minified JS code too - by hand, but I guess you have some sort of minifier/obfuscator to do that job...

Alex

Coordinator
Feb 18, 2010 at 4:11 PM

Alex,

Is SPSetMultiSelectSizes called before SPCascadeDropdowns? Marc had to set me straight on my use of the function once for doing something similar to what I think you are. I was calling SPSetMultiSelectSizes on the completefunc of SPCascadeDropdowns, so the multi-selects would resize every time I changed the parent field. In reality, if you call SPSetMultiSelectSizes as the first thing in your $(document).ready, it should size to the width of the longest value in the source list, before SPCascadeDropdowns filters it to the current selection in the parent field, then you shouldn't have to re-run SPSetMultiSelectSizes every time SPCascadeDropdowns runs.

Mike

 

Feb 18, 2010 at 4:17 PM

Mike,

Yes, I see what you are saying. And yes, my call to SPSetMultiSelectSizes is in the completefunc of SPCascadeDropdowns. Moving it to before SPCascadeDropdowns is called helps a lot.

I still need to restrict the width of the multi-select lists though, as I have some values in the multi-select that are rather long...

Thanks,
Alex

Coordinator
Mar 1, 2010 at 9:00 PM

Alex:

Thanks for your feedback on this.  The way I wrote SPSetMultiSelectSizes is to look at all of the values in the multi-select and set the boxes based on the longest values present (taking into account the fontsize, etc.).  Are you wanting the function to not take into account the longest values, but just use a fixed width? 

M.

Mar 2, 2010 at 2:07 PM

Marc,

The problem I have is that some of the values in the multi-select are really quite long, and so the result of using SPSetMultiSelectSizes is that the left and right <select> boxes become waaaaay too wide. The code that calculates the width of the longest value is still important and necessary because that's how big the actual <select> boxes are, but the surrounding <div> is sized smaller, and allow for scrolling.

Alex

Coordinator
Mar 2, 2010 at 4:36 PM

The selects are going to be as big as they need to be; the browser takes care of that.  I sort of see your point, but the whole reason for the SPSetMultiSelectSizes, as I saw it, was to remove the scrolling altogether.  However, you've got a valid need, and a decent extension to the function to make it happen.  I'll look at it more and try to get it into the next release or so.

Thanks,
M.