Tuesday, June 10, 2008

Hiding List View Group Headers

It’s really annoying that SharePoint displays those pesky column names followed by a colon when you group by a column. In this example I use the the columns “Categoria” and “Titulo” to group a bunch of pages.

image

In addition, the gray header row is ugly, too.

We can hide it with some Content Editor Web Part (CEWP) and JavaScript magic.

The offending elements can be identified:

image

We have to hide the following elements:

  • a TR element with class name ms-viewheadertr (the header row)
  • the fourth and the fifth child of a TD element with class names ms-gb (the column name of the first group by and a colon)
  • the fourth and the fifth child of a TD element with class names ms-gb2 (the column name of the second group by and a colon)

I use the excellent getElementsByClassName function developed by Robert Nyman in order to get those elements by class name.

This is the code to be pasted in a CEWP at the same page where you have the “ugly” list view. Please note that the text node which contains the colon must be removed instead of being hidden.

<script type="text/javascript" language="javascript">
_spBodyOnLoadFunctionNames.push("HideHeaders");

function HideHeaders()
{
  var elements = getElementsByClassName(document, "td", "ms-gb");
  var elem;
  for(var i=0;i<elements.length;i++)
   {
     elem = elements[i];
     elem.childNodes[3].style.display = "none";
     elem.removeChild(elem.childNodes[4]);
   }

  elements = getElementsByClassName(document, "td", "ms-gb2");

  for(var i=0;i<elements.length;i++)
   {
     elem = elements[i];
     elem.childNodes[3].style.display = "none";
     elem.removeChild(elem.childNodes[4]);
   }

  elements = getElementsByClassName(document, "tr", "ms-viewheadertr");

  for(var i=0;i<elements.length;i++)
   {
     elem = elements[i];
     elem.style.display = "none";
   }
}

/*
    Written by Jonathan Snook, http://www.snook.ca/jonathan
    Add-ons by Robert Nyman, http://www.robertnyman.com
*/
function getElementsByClassName(oElm, strTagName, strClassName){
    var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
    var arrReturnElements = new Array();
    strClassName = strClassName.replace(/\-/g, "\\-");
    var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
    var oElement;
    for(var i=0; i<arrElements.length; i++){
        oElement = arrElements[i];
        if(oRegExp.test(oElement.className)){
            arrReturnElements.push(oElement);
        }
    }
    return (arrReturnElements)
}
</script>

This is the result of this code:

image

Much better, isn’t it?

19 comentarios:

sarahsez said...

Hi, Edin: I can't quite get your great tip to work--not only do the column header and colon (thankfully) disappear, but so also do the column values. Instead of seeing Comites (1), I just see (1) to the right of the expansion control. Something I should/shouldn't be doing? Thanks -- Sarah

Edin said...

Can you check in the source code of the rendered page that the TD element with class = "ms-gb" has the right number of child nodes beneath it. The fourth node should be the category name and the fifth should be the colon.

I just noticed that in the post I mention them to be the third and the fourth child. I will correct it now.

If your rendering is different, adjust the number in these sentences:

// This hides the category elem.childNodes[3].style.display = "none";

// This hides the colon elem.removeChild(elem.childNodes[4]);

Tudor Olariu said...

Your javascript code would be much, much simpler, easier and faster if you would use jquery. For example, the function "getElementsByClassName" is provided by default in jquery, and the implementation is faster as it doesn't iterate through all the elements with the same tag name in search of the specific class.

Also you would need to make sure you are only manipulating the "ms-gb" (for example) class which are inside a grouped list view.

Edin said...

Tudor, thank you for your suggestion.

I do use jQuery in some of my projects, but I wanted to illustrate the concept of how to hide the elements and I didn't want to use a specific external library.

Tudor Olariu said...

Hello again,

Back with another suggestion, you can delete the unwanted sections from your view my changing the grouped view into an xslt data view using SharePoint Designer and alter the XSLT transformation from within. See http://tudorolariu.blogspot.com/2008/10/custom-group-order-in-sharepoint-list.html for more information.

Edin said...

Hi Tudor,

The changes that you are suggesting would customize the page and break the page definition. I've used this technique sometimes but I'd come to dislike the SharePoint Designer meddling with pages. I prefer to stick to packaged, manageable changes that can be provisioned and unprovisioned.

Anonymous said...

Thanks for this. I fixed the issue above by changing:

elem.removeChild(elem.childNodes[4]);

to

elem.childNodes[4].nodeValue = elem.childNodes[4].nodeValue.replace(':', '');

Anonymous said...

This is a really cool job!!
Can we make it perfect by removing the number of element of the group(1)? :P

Anonymous said...

Is there any other way to hide/un-hide ListView Column without using CSS Class?

Edin said...

If you want to hide a ListView column entirely, you can just remove it from the view columns in the view settings.

Eihab said...

This is great job; thanks for it. but I wonder is there a simple way of getting rid of the (1) that displays next to the displaying headers. your help is much appreciated.
Thanks,
Eihab

Rajesh Agadi said...

Great solution. I hate to meddle with SPD and hate to update the VWSTYLS.XML

Worked like charm.

I have to change the lines

from

elem.removeChild(elem.childNodes[4]);

to

elem.childNodes[4].nodeValue = elem.childNodes[4].nodeValue.replace(':', '');

Thanks Much!

RBsandoval said...

Edin,
Do you have this as jQuery code? Would it work for a list in SP v.2 (SharePoint 2003)?

Robert Sandoval

Edin said...

Hi Roberto,

No, I don't have this as a jQuery code but it shouldn't be rocket science. It's surely much easier.

I think that the CSS class names are the same in SharePoint 2003 and 2007 for the groupings, so it should work. Haven't tested it yet.

Anonymous said...

Beginner note -> this script wasn't working for me, until I figured out the the function (HideHeaders) wasn't being launched. For some reason the _spBodyOnLoadFunctionNames.push("HideHeaders"); was being ignored.

To fix it, I simply added
HideHeader(); to the top of the page, right before function HideHeaders()

-----------
_spBodyOnLoadFunctionNames.push("HideHeaders");

HideHeaders();

function HideHeaders()
{

-----
worked after that. Thank you for posting this!

Anonymous said...

This is a great solution and I have been using it for a couple of years. Do you have a version of this working for SharePoint 2010?

excelhacker said...

for sharepoint 3.0 you will need to comment out the following:


/*elem.removeChild(elem.childNodes[4]); */

excelhacker said...

one last thing
under the commented out section, add the following to remove the colon


elem.childNodes[4].data=elem.childNodes[4].data.replace(':','');

Michael Bollhoefer said...

I was having trouble getting this code to work even with the comments and it was because the nodes elements were different sometimes. I generacized it so will work on different length nodes and also on subcontenttypes as well. I just added it into a content editor web part and then set the chrome to none and checked the hidden box and renamed it to "Hide Column Headers Script". Exported the webpart and then added it to the webpart gallery so that it was easy to add this to any page in the future. Let me know if this works for you.

_spBodyOnLoadFunctionNames.push("HideHeaders");


function HideHeaders()
{
var elements = getElementsByClassName(document, "td", "ms-gb");
var elem;
for(var i=0;i<elements.length;i++)
{
elem = elements[i];
elem.childNodes[elem.childNodes.length-3].childNodes[1].data = "";
elem.childNodes[elem.childNodes.length-2].data=elem.childNodes[elem.childNodes.length-2].data.replace(':','');
}


elements = getElementsByClassName(document, "td", "ms-gb2");


for(var i=0;i<elements.length;i++)
{
elem = elements[i];
elem.childNodes[elem.childNodes.length-3].childNodes[1].data = "";
elem.childNodes[elem.childNodes.length-2].data=elem.childNodes[elem.childNodes.length-2].data.replace(':','');
}


elements = getElementsByClassName(document, "tr", "ms-viewheadertr");


for(var i=0;i<elements.length;i++)
{
elem = elements[i];
elem.style.display = "none";
}
}


function getElementsByClassName(oElm, strTagName, strClassName){
var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
var arrReturnElements = new Array();
strClassName = strClassName.replace(/\-/g, "\\-");
var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
var oElement;
for(var i=0; i<arrElements.length; i++){
oElement = arrElements[i];
if(oRegExp.test(oElement.className)){
arrReturnElements.push(oElement);
}
}
return (arrReturnElements)
}

Post a Comment