Truncating multiple lines of text SPField in a list


One thing I have noticed with users for SharePoint, is that they like using lists as if it was excel. The views have all the columns in it, and the notes/description fields are filled with lines of text, which blows out the page. You are lucky to see any more than 2 items on the page, and after a lot of scrolling you reach the bottom. Wouldn’t it be nice to have all that text truncated in the list? Wouldn’t it also be better that your users could modify the settings so that they could change the (Show More) link, or display more words? Wouldn’t it be cruel of me now not to tell you how to do this, after you have Google this and found out that this is what you wanted? (Yes, but I’m not going to do that). I have been able to do this by adding a WebPart (that is hidden) onto the page that inserts JavaScript into the page. The JavaScript finds all multiple lines of text fields and then perform Jquery command (via a plugin) on them to truncate the text. The WebPart has configurable settings to allow it to be changed by the user. The Jquery plugin credit goes to Keith Wood. You can download the plugin directly from his site http://keith-wood.name/more.html. This site also has documentation on how to use the plugin.

Building the WebPart.

Prerequisite to this WebPart is to ensure Jquery is enabled on the page you are adding the WebPart to. I have written a blog on adding JQuery to your site using a Sandbox and Farm Solution that will help you.

  1. Create a new Blank SharePoint Project in Visual Studio, set as a Farm solution.
  2. Add a Visual WebPart. This will automatically create a Feature for you. Rename the feature, and remember to add the Visual WebPart to the feature. (Number of times I’ve been caught out by this).
  3. Add the jquery.more.min.js file from http://keith-wood.name/more.html to your Visual WebPart. In the properties change the deployment type to ClassResource and the Deployment location path to Scripts\

    Note: The reason why we use ClassResource instead of the Layouts folder is because it will be cached. The script will be loaded from the server only the first time it is referenced, and all references therafter will be loaded from the browser’s cache.
  4. As it stands, build and deploy your webpart. You don’t need to add it to the page yet. Navigate to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\wpresources you should find a folder in there with the same name as your project. Open that folder and inside you will have a folder named similar to 1.0.0.0__a08a25e201fade25. Inside that folder you will see your Scripts folder, and lastly inside that you will see the jquery.more.min.js file. Take note of the path from the folder of the project name to the JavaScript file. In my case this is TruncatingNotes\1.0.0.0__a08a25e201fade25\Scripts\jquery.more.js
  5. Open the user control .ascx page. Add the line (remembering to put your path name)
    <script type="text/javascript" src="_wpresources/TruncatingNotes/1.0.0.0__a08a25e201fade25\Scripts\jquery.more.js"></script>
    
  6. Add a new JavaScript file to the project and call it expand.js. In the properties change the deployment type to ClassResource and the Deployment location path to Scripts\
  7. In the expand.js file put the following JavaScript
    function collapseText(group){
    if(!group) group = "#MSO_ContentTable";
    $(group + " td.ms-vb2&gt;div").each(function (i, e){
    $(e).more({ length: myLength, leeway: myLeeway, wordBreak: myWordBreak, ellipsisText: myEllipsisText, moreText: myMoreText, lessText: myLessText });
    });
    }
    $(function() {
     collapseText();
    });
    

What the code above is actually doing is looking for each Notes field and then with the jquery plugin (e).more() passing in the user parameters. This in turn truncates each note field. (Sorry wordpress for some reason wouldn’t let me continue numbering, so back to 1.)

  1. Add a new css file to the project and call it Truncate.css. In the properties change the deployment type to ClassResource and the Deployment location path to Styles\.
  2. In the Truncate.css add the following css:
    .more-hidden {display: none;}
    .more-link {margin-left: 1em;padding: 0.125em;-moz-border-radius: 0.25em;-webkit-border-radius: 0.25em;text-decoration: none;}
    .more-link img {border: none;}
    

    The above css names are defined in the Jquery plugin documentation.

  3. Back on the user control .ascx page, now add the script and css link to the two new files. (remember to put your path name)
    <script type="text/javascript" src="_wpresources/TruncatingNotes/1.0.0.0__a08a25e201fade25\Scripts\expand.js"></script>
    <link type="text/css" rel="Stylesheet" href="_wpresources/TruncatingNotes/1.0.0.0__a08a25e201fade25\Styles\Truncate.css"></script>
    
  4. Now we need to set up the WebPart to have user configurable settings. Open up the WebPart .cs file. Add the following user settings within the WebPart class.
    [Category("Truncated Settings"),
    WebBrowsable(true),
    Personalizable(PersonalizationScope.Shared),
    WebDisplayName("Text Length"),
    WebDescription("The number of characters shown after truncation.")]
    public UInt32 TextLength { get; set; }
    
    [Category("Truncated Settings"),
    WebBrowsable(true),
    Personalizable(PersonalizationScope.Shared),
    WebDisplayName("Text Leeway"),
    WebDescription("The number of additional characters allowed before truncation is actually applied.")]
    public UInt32 TextLeeway { get; set; }
    
    [Category("Truncated Settings"),
    WebBrowsable(true),
    Personalizable(PersonalizationScope.Shared),
    WebDisplayName("Word Break"),
    WebDescription("When unselected the text is truncated at the character specified by Text Length, regardless of its position within a word. When selected the text is truncated at the first word boundary before Text Length")]
    public bool AllowWordBreak { get; set; }
    
    [Category("Truncated Settings"),
    WebBrowsable(true),
    Personalizable(PersonalizationScope.Shared),
    WebDisplayName("Ellipsis Text"),
    WebDescription("The text used at the end of a truncation to indicate that more text is available.")]
    public string EllipsisText { get; set; }
    
    [Category("Truncated Settings"),
    WebBrowsable(true),
    Personalizable(PersonalizationScope.Shared),
    WebDisplayName("More Text"),
    WebDescription("The text shown on the link to expand the text.")]
    public string MoreText { get; set; }
    
    [Category("Truncated Settings"),
    WebBrowsable(true),
    Personalizable(PersonalizationScope.Shared),
    WebDisplayName("Less Text"),
    WebDescription("The text shown on the link to collapse the text.")]
    public string LessText { get; set; }
    
  5. To ensure that we can access these parameters within the UserControl replace what is inside CreateChildControls() method with the following
    var control = Page.LoadControl(_ascxPath) as TruncatedWebPartUserControl;
    if(control != null)
    {
     control.WebPart = this;
     Controls.Add(control);
    }
     
  6. Open up the .cs of the UserControl. The following code will create a global variable for the WebPart so we can retrieve the parameter values, then on a PreRender we will create the JavaScript variables and add them to the page. As you can see the JavaScript variables match the variables in the expand.js file. Lastly if using in production environment I would escape your parameters before passing them. You don’t want a script attack.

    public partial class TruncatedWebPartUserControl : UserControl
    {
    public TruncatedWebPart WebPart { get; set; }
    public TruncatedWebPartUserControl()
    {
     this.PreRender += new EventHandler(TruncatedWebPartUserControl_PreRender);
    }
     void TruncatedWebPartUserControl_PreRender(object sender, EventArgs e) {
    //Create the JavaScript Variables then add to the page.
    var embeddedScript = String.Format("<script language=\"javascript\">
    var myLength = {0};" +
    "var myLeeway = {1};" +
    "var myWordBreak = {2};" +
    "var myEllipsisText = \"{3}\";" +
    "var myMoreText = \"{4}\";" +
    "var myLessText = \"{5}\";" +
    "</script>",
    WebPart.TextLength,
    WebPart.TextLeeway,
    WebPart.AllowWordBreak.ToString().ToLower(),
    WebPart.EllipsisText,
    WebPart.MoreText,
    WebPart.LessText);
    ClientScriptManager cs = Page.ClientScript;
    if (!cs.IsClientScriptBlockRegistered("Parameters"))
    cs.RegisterClientScriptBlock(
    this.GetType(),
    "Parameters",
    embeddedScript);
    }
    }
    

    You could just deploy the WebPart and all would work fine once you have configured it, but this next step will pre-configure the WebPart when it is added to the page. Open the .webpart file and add these additional properties. Because I used UInt I needed to include the full type.

    <property name="Hidden" type="bool">True</property>
    <property name="TextLength" type="System.UInt32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089>20</property>
    <property name="TextLeeway" type="System.UInt32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">5</property>
    <property name="AllowWordBreak" type="bool">True</property>
    <property name="EllipsisText" type="string">...</property>
    <property name="MoreText" type="string">(Show More)</property>
    <property name="LessText" type="string">(Show Less)</property>
    
  7. Deploy the solution to your server, activate the feature if necessary. Goto a library that has long multiple lines of text showing. Add the webpart to the page and save the page.

    To download the project without typing it all out yourself http://sdrv.ms/YYyQY3 There is also some other bits of code that I’ve added to the project to make it act and feel like a proper WebPart solution.

Advertisements