1

I would like to display my calculated columns fields in plain text in the filtering drop-down menu when I click on the column title.

I don't know why SharePoint displays my calculated formula instead of my fields, it's not really usefull as filter options for the user.

Have you ever encountered this issue?

I'm using SharePoint 2007 (MOSS), and I don't have permissions to use SharePoint Designer or an other software/solution.

I'm sure I can modify this with JavaScript in a CEWP.

I need help guys... this is making me crazy...

EDIT: I uploaded an image, maybe it is easier to understand my needs.

Here is the situation, I clicked on the column title in order to open the filtering menu (top right corner), instead of displaying me "New", "In progress" and "Closed", my 3 Status fields, it shows me my calculated formula that I used to render my fields in color.

Filtering issue

1
  • I actually wrote my answer in your last one, but it took me 15 mins to write, and you deleted before I could post, so I'll stick it here for now. Get ready for a novel
    – Brandon C.
    Jun 26, 2014 at 8:47

4 Answers 4

2

Okay, I solved it. And you can't tell me it doesn't work, because I can see it with my own eyes :) So, that javascript you are running from that guy is unecessary, and it makes things more difficult that they should be. So you have three columns. One column has the status, one column determines the color, and the final column has the div tags. And it's the div tags that are causing the problem. So, to do it my way, you really only need one column, your status column. You will actually be using my script to refilter the status column. You will still have to find the indexes again, but it is much more simple than earlier. Again, find the ID of your table. From the table, reference the body that contains all your elements. I will show you what things in my script stand for.

document.getElementById("ID_of_Table").children[2]  //my <tbody> element
document.getElementById("ID_of_Table").children[2].children[4] //one row in my table
document.getElementById("ID_of_Table").children[2].children[4].children[3]  //one field in my table

What you want to do, is have the script cycle through all the rows.

<script type="text/javascript">
function recolorThis() {

  //First, we cycle through the rows
  for(i=1; i<document.getElementById("ID_of_Table").children[2].children.length; i++) {

     //Now we cycle through the each field in one row
     for(j=0; j<document.getElementById("ID_of_Table").children[2].children[i].children.length; j++) {

        //Now we will change text according to what is in that field
        if(document.getElementById("ID_of_Table").children[2].children[i].children[j].innerHTML == "New") {
           document.getElementById("ID_of_Table").children[2].children[i].children[j].innerHTML = document.getElementById("ID_of_Table").children[2].children[i].children[j].innerHTML.replace(/New/, "<div style='font-weight:bold; font-size:24px; color:#00FF00'>New</div>");
          }
        if(document.getElementById("ID_of_Table").children[2].children[i].children[j].innerHTML == "In Progress") {
           document.getElementById("ID_of_Table").children[2].children[i].children[j].innerHTML = document.getElementById("ID_of_Table").children[2].children[i].children[j].innerHTML.replace(/In Progress/, "<div style='font-weight:bold; font-size:24px; color:#FFFF00'>In Progress</div>");
           }

        if(document.getElementById("ID_of_Table").children[2].children[i].children[j].innerHTML = "Closed") {
           document.getElementById("ID_of_Table").children[2].children[i].children[j].innerHTML = document.getElementById("ID_of_Table").children[2].children[i].children[j].innerHTML.replace(/Closed/, "<div style='font-weight:bold; font-size:24px; color:#FF0000'>Closed</div>");
           }

       }  //Closing the j for loop
     }   //Closing the i for loop
  }    //Closing the function

window.onload = recolorThis();
</script>

So what my script does, is it takes the entire table of elements in our list, and it cycles through each element row by row, field by field, until it finds a field containing any of your statuses. When it finds one, depending on what it says, it will replace the text with a tag, that is styled to how you want. However, this does nothing to change the actual data in the server, it is still just the simple "New", "In Progress", and "Closed" strings, so that's all that will be displayed in the filter menu.

Of course, you can completely eliminate the second for loop if you know where the text in the fields can be referenced from, increasing performance. I know the replace function works, I tested it on my site. I felt like I owed you at least a decent answer before giving up.

16
  • I'm trying it, thank you for your try hardingness Brandon :)
    – Funnybear
    Jun 27, 2014 at 13:35
  • No problem, felt like I owed you an answer I was satisfied with after throwing so much information at you, haha.
    – Brandon C.
    Jun 27, 2014 at 13:41
  • I made a mistake in the code, will post the updated version. I tested the whole script on mine, it works :)
    – Brandon C.
    Jun 27, 2014 at 14:05
  • Ahhh.. I changed it myself before you update the code, it was the .children ?
    – Funnybear
    Jun 30, 2014 at 8:24
  • Oh, awesome! So does it work for you?
    – Brandon C.
    Jun 30, 2014 at 8:36
1

Okay, this is a very verbose answer, only because I cannot think of another way around this. I will try to answer this as easily as I possibly can (no offense to you, I don't mean to make it sound like I am trying to speak down to you, it just involves a lot of steps that involve arguments that will be different for me as they are for you. To answer your question upfront though, I was able to change the text in the filter menu through one line of javascript, but it took 20 minutes to figure out that one line.

To start, open your site page in chrome or firefox (that's right, it's time to do some tag searching). And just so you know, none of the HTML elements exist (are null) if the filter menu isn't open, so make sure you have the filter menu open at all times while doing this (on mine it constantly closes after some time, just quickly double click on some text in the source code to stop it from closing if it happens to you).

So the column that has the incorrect filter text should have a unique ID in the tag, I'll call it "ID_of_dumb_column" in this answer. So now we know how to reference that. Now, in the HTML, this column has three child elements. We want the one with the class named something like "ms-core-menu-box". For me, it was the third tag that contained it for me. To do this, follow as such:

document.getElementById("ID_of_dumb_column").children[2]  //Indexes start at 0

The .children property will return all tags contained within that tag, and stores it into an "array". When you expand that tag in the debugger, you should see another ul element. Even though there is only one tag, we need to still reference it like an array. Again:

 document.getElementById("ID_of_dumb_column").children[2].children[0]

So now we are referencing the ul tag. Expand the ul tag in the debugger, and you should find li tags. These lines are now the HTML tags referincing the rows in the filter menu (The "A on top", "Z on top", "" stuff). Move your mouse over the various li tags to find the ones that correspond to the options you want to change (for me, my first option was at index 4). To reference this, we write:

  document.getElementById("ID_of_dumb_column").children[2].children[0].children[4]

I'm going to speed up a little to shorten this already wall of text. Inside the li tag, there's one a tag at index zero, so do the children thing again for index 0. Inside the a tag, there are 3 div tags. I want the one called "labelcompact", it should be the one that covers the text. For me, that is at index 1, so I call children again at index 1. Finally, in that div tag there is a span that has the title. For me, that was at index 0. Then we set the innerHTML text of that tag.

So FINALLY I have this:

 document.getElementById("ID_of_dumb_column").children[2].children[0].children[4].children[0].children[1].children[0].innerHTML = "New";  //OR whatever yours is supposed to be

Then we want to make sure this line of Jscript is ONLY called when the menu is open, so in your script, write:

<script type="text/javascript">
function myfunction() {
document.getElementById("ID_of_dumb_column").children[2].children[0].children[4].children[0].children[1].children[0].innerHTML = "New";
document.getElementById("ID_of_dumb_column").children[2].children[0].children[5].children[0].children[1].children[0].innerHTML = "In Progress";
document.getElementById("ID_of_dumb_column").children[2].children[0].children[4].children[0].children[1].children[0].innerHTML = "Closed";
}

document.getElementById("ID_of_dumb_column").onmousedown = myfunction;
</script>

For me, this worked, it changed the text in my filter menu to what I set it as. The only thing you have to change to change the other options, is move the .children[4] up or down to get all the different li tags for each text you want to change.

Should it work? Yes. Is it a good answer? Heck no, and I'm sure there are better ones out there, but this is all I can think of, and when I tested the .children lines out in firefox debugger, the text changed. To wrap this up, my layout is different than yours, so your numbers will DEFINITELY be different than mine, and you may have more or less children calls. Just spend the next half hour or so parsing through the debugger, finding out where the incorrect text lies, and then write a line to travers down, starting from the column ID call.

I really hope this helps! :)

<script type="text/javascript">
function myNewFunction() {
  document.body.innerHTML = document.body.innerHTML.replace(/<DIV font.../g, 'New');  //Fill in the DIV stuff with the whole line that appears in the filter text
  document.body.innerHTML = document.body.innerHTML.replace(/<DIV font.../g, 'In Progress');
  document.body.innerHTML = document.body.innerHTML.replace(/<DIV font.../g, 'Closed');
 }

window.onClickFilter = myNewFunction;
</script>

Careful though, while this is quick, if you reference the text, it might cause problems

9
  • I'm testing your answer. If I have to do it for 3 columns in several views (6 or 7), I have to create a CEWP for each view and repete the script for each columns? Thank you very much, even if it's not the perfect answer, actually it's something to explore. I will give it a try, if it works with you, I should be able to do it. I'll let you know my feedback if i'm stuck or w/e.
    – Funnybear
    Jun 26, 2014 at 9:14
  • Actually, think I found a better option, look at the last part of my answer
    – Brandon C.
    Jun 26, 2014 at 9:36
  • There is something I don't understand, when you say my buggy column has "a unique ID". I'm OK with that, but with Chrome (F12), I tried to see if the id change depending with the column. I created 3 calculated columns in my list with the buggy filtering menu. THe ID is always "filter_menu", it's just the numbers of childs which change. I have the first child "A on top" option, then "Z on top" option, then "Clear Filter from 'myColumnName'" option and finally all my field option with the <DIV etc.. Am I going in a wrong way?
    – Funnybear
    Jun 26, 2014 at 12:26
  • You can always change the ID value. All the ID value does is let that item be specifically referenced. It won't change any properties about the tag itself. So you can rename it to whatever you want, to make sure it is a unique ID.
    – Brandon C.
    Jun 26, 2014 at 12:28
  • Ok I'm more comfortable now with HTML/JS. The filtering menu that disappears annoy me so much, when I switch Console/Elements.. Anyways, I can't find the child with the class named "ms-core-menu-box", I even used the search box.
    – Funnybear
    Jun 26, 2014 at 13:30
0

@BrandonC.

var t = document.getElementById("{6638F2B6-64E3-4D26-BE78-24E38C8F3847}-{B7E882E9-A099-47D1-95C9-9E8CAF00E5B7}");


for(i=1; i<t.getElementsByTagName("tbody")[0].children.length; i++) {

It doesn't "enter" in the loop, I wrote something wrong? My ID is too long, that's why I created a variable.

t.getElementsByTagName("tbody")[0].children.length

This displays me "49" in the console, the numbers of rows in my table, I don't understand why I can't enter in the loop, I'm trying to display a "test message" after the For loop without success.

2
  • Why downvote? I don't understand this behaviour
    – Funnybear
    Jun 30, 2014 at 11:43
  • Sorry, it wasn'T me who downvoted :( Sorry, I have not seen the notifcation for this answer, so I am just seeing it now. I am unsure why this is happening, I will try to figure it out myself :)
    – Brandon C.
    Jun 30, 2014 at 12:53
0

Here is the script that I use :

 <script type="text/javascript">
 function recolorThis() {

var t = document.getElementById("{6638F2B6-64E3-4D26-BE78-24E38C8F3847}-{B150AAD8-6D16-46ED-98BF-8CFBC3E4BF20}");

//First, we cycle through the rows
for(i=1; i<t.children[0].children.length; i++) {

 //Now we cycle through the each field in one row
 for(j=0; j<t.children[0].children[i].children.length; j++) {  

    //Now we will change text according to what is in that field
    if(t.children[0].children[i].children[j].innerHTML = "New") {
       t.children[0].children[i].children[j].innerHTML = t.children[0].children[i].
       children[j].innerHTML.replace(/New/, "<div style='font-weight:bold; font-size:24px; color:#00FF00'>New</div>");
      }

    else if(t.children[0].children[i].children[j].innerHTML = "In progress") {
       t.children[0].children[i].children[j].innerHTML = t.children[0].children[i].
       children[j].innerHTML.replace(/In progress/, "<div style='font-weight:bold; font-size:24px; color:#FFFF00'>In progress</div>");
      }

    else if(t.children[0].children[i].children[j].innerHTML = "Closed") {
       t.children[0].children[i].children[j].innerHTML = t.children[0].children[i].
       children[j].innerHTML.replace(/Closed/, "<div style='font-weight:bold; font-size:24px; color:#FF0000'>Closed</div>");
      }

    else {
       window.alert("error");
      }


     }  //Closing the j for loop
   }   //Closing the i for loop
 }    //Closing the function

window.onload = recolorThis();
</script>
11
  • 1
    Change every if(t.children[0].children[i].children[j].innerHTML = "") To if(t.children[0].children[i].children[j].innerHTML == ""). When I wrote the code, I forgot the two ==. When you only have one =, the statement is always true, unless there is a typecast error.
    – Brandon C.
    Jun 30, 2014 at 13:18
  • The table of elements ID is different in each views, that means I will add a CEWP with a different script for each views. I think I have no other choice.
    – Funnybear
    Jun 30, 2014 at 13:20
  • Ahhhh... I'm a noob... it's always "==" or ";" the problem, I should have known it...
    – Funnybear
    Jun 30, 2014 at 13:21
  • Haha, don't worry, I'm the one that wrote the original mistake anyways. Yeah, as far as my solution goes, you will have to do it for each view. If I think of a way, I'll let you know in an update :(
    – Brandon C.
    Jun 30, 2014 at 13:24
  • Ok many thanks Brandon, you were very helpful (Tons of reputation now? xD)
    – Funnybear
    Jun 30, 2014 at 13:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.