1

Here's my situation. I have a DispForm that has two Data View Web Parts at the top that are displaying a few related items from two other lists. What I've been trying to figure out for hours now is how to change the entire background color of one of the list web parts at the top when any list item has a value for 'Status' column that is '0 A - Contract Signed'.

I've gotten the following code to do half the job:

function listFormat() {

    $Text = $("td .ms-vb2:contains('0 A - Contract Signed')");
    $Text.parent().css("background-color", "Red"); }

$(document).ready(function(){
    listFormat()
}); 

window.onhashchange = listFormat;

This looks down the Status column and if it sees '0 A - Contract Signed' on any of the listed items, it highlights the row of that particular item Red. Now, the next step I want to take is instead of just highlighting that particular row Red, I want to change the background of the entire Data View Web Part red. To do that, I need to change the target from "parent()' to '#WebPartWPQ7" (and eventually WebPartWPQ8 but I'll worry about that once I figure out how to do one of them.)

After a lot of searching about the proper syntax, I sort of got it to work with this:

function listFormat() {

    $Text = $("td .ms-vb2:contains('0 A - Contract Signed')");
    $("#WebPartWPQ7").css("background-color", "Red"); }

$(document).ready(function(){
    listFormat()
}); 

window.onhashchange = listFormat;

The data view web part's background does turn red, but it turns red no matter if it finds '0 A - Contract Signed' in the list of items or not (or even if the list is blank.)

How can I get it to change the entire web part background red if it finds that status otherwise go with the default background?

Thanks for everyone's help!


EDIT: Got it working thanks to help from @DylanCristy. The other challenge I didn't mention was that with the two list web parts at the top, I needed them to both have background color changed to red whenever the status changed to a particular status. The tricky part with List Web Parts is that the ID of individual cells in the lists are usually just that "td .ms-vb2' and they're not all unique. If I was smarter, I'd figure out a way to individually target them but I couldn't. So, I ended up just saying fine, watch all targets on this page called "td .ms-vb2" for the Status '0 A - Contract Signed' on one web part and the Status 'QA - Passed' on the other. If you see it at all, highlight this particular web part that has that particular status.

Here's what the code looks like which may help make that easier to understand:

    function listFormat() {



var $Text = $("td .ms-vb2:contains('0 A - Contract Signed')");
if ($Text.length > 0) {
    $("#WebPartWPQ7").css({"background-color": "#ff8a8a", "border-radius": "0px 0px 10px 10px"});
}
if ($Text.length > 0) {
    $("#WebPartWPQ7_ChromeTitle").css("margin-bottom", "-2px");
}



var $Text = $("td .ms-vb2:contains('QA - Passed')");
if ($Text.length > 0) {
    $("#WebPartWPQ6").css({"background-color": "#ff8a8a", "border-radius": "0px 0px 10px 10px"});
}
if ($Text.length > 0) {
    $("#WebPartWPQ6_ChromeTitle").css("margin-bottom", "-2px");
}

}

    $(document).ready(function(){
        listFormat()
    }); 

    window.onhashchange = listFormat;

I couldn't figure out how to easily apply two different sets of CSS changes to two different selectors (#WebPartWPQ7 and #WebPartWPQ7_ChromeTitle for example.) So I just basically copy and pasted the if statement twice. I know there's a way to make that more efficient but just don't know how and I've already spent way too many hours on this problem. :)

Thanks again for the help Dylan!


EDIT2:

Thanks Dylan! Here's my final code for those who are interested. Working exactly as intended. BTW, if anyone's curious about why the -2 px on the bottom margin of the ChromeTitle, it's because when you shade the background of the web part (as done in that first step) there's this little gap between the title area and the main table where it's not colored. Taking away -2 px from the bottom margin of the title closes that gap so the colored background meets right up below the colored title bar.

<script>
    function listFormat() {



var $waiting = $("td .ms-vb2:contains('2 E - Waiting for build')");
var $failed = $("td .ms-vb2:contains('2 I - Failed QA')");
if ($waiting.length > 0 || $failed.length > 0) {
    $("#WebPartWPQ7").css({"background-color": "#ffb20099", "border-radius": "0px 0px 10px 10px"});
}
if ($waiting.length > 0 || $failed.length > 0) {
    $("#WebPartWPQ7_ChromeTitle").css("margin-bottom", "-2px");
}



var $failed2 = $("td .ms-vb2:contains('Failed QA')");
var $dev = $("td .ms-vb2:contains('Contacted Dev')");
var $waiting2 = $("td .ms-vb2:contains('Waiting on New Build')");
var $failed3 = $("td .ms-vb2:contains('Failed Wrap QA')");
if ($failed2.length > 0 || $dev.length > 0 || $waiting2.length > 0 || $failed3.length > 0) {
    $("#WebPartWPQ6").css({"background-color": "#ffb20099", "border-radius": "0px 0px 10px 10px"});
}
if ($failed2.length > 0 || $dev.length > 0 || $waiting2.length > 0 || $failed3.length > 0) {
    $("#WebPartWPQ6_ChromeTitle").css("margin-bottom", "-2px");
}

}

    $(document).ready(function(){
        listFormat()
    }); 

    window.onhashchange = listFormat;


</script>
1

The problem in your second example is that you abandon checking to see if you actually found an element that meets the conditions of your first selector. (In truth, you don't really check in the first example either, but jQuery magically takes care of it for you behind the scenes.)

You can't just do

// you also should have a proper variable declaration using "var"
var $Text = $("td .ms-vb2:contains('0 A - Contract Signed')");
if ($Text) {
    $("#WebPartWPQ7").css("background-color", "Red");
}

Because jQuery will always give you back an object, so that will always evaluate to true even if you didn't get a match. Another alternative would be to check the length property, because what jQuery is giving you is actually a collection. So you could do

var $Text = $("td .ms-vb2:contains('0 A - Contract Signed')");
if ($Text.length > 0) {
    $("#WebPartWPQ7").css("background-color", "Red");
}

Or, you could let jQuery handle checking if you found a match the same way you do in your first example, and use jQuery's closest( selector ) function to traverse up the DOM tree until you find the element that matches the selector, so something like

var $Text = $("td .ms-vb2:contains('0 A - Contract Signed')");
$Text.closest("#WebPartWPQ7").css("background-color", "Red");

In order to get away from being tied to the WebPartWPQ7 ID, you could inspect the page and see if there is a class you could latch on to:

var $Text = $("td .ms-vb2:contains('0 A - Contract Signed')");
$Text.closest(".someClassOnTheParentWebpart").css("background-color", "Red");

or just count how many steps up the DOM the webpart is from your td, and just chain parent() calls, so if it's 5 levels up:

var $Text = $("td .ms-vb2:contains('0 A - Contract Signed')");
$Text.parent().parent().parent().parent().parent().css("background-color", "Red");

To see a whole bunch of options, check out the jQuery cheat sheet, and look at the section called "Tree Traversal".


To address your comment:

In order to check for multiple values, the way you are doing it, you will have to write multiple selectors, because :contains will only work with one value. So you would have to do something like

var signed = $("td .ms-vb2:contains('0 A - Contract Signed')");
var failed = $("td .ms-vb2:contains('Failed QA')";
var contacted = $("td .ms-vb2:contains('Contacted Dev');
// etc

and work with that. The better way to do something like that would be to somehow identify exactly which table cell is going to have the status, get it's value, and check it in code without using the :contains selector, and do something like

// and this isn't really going to work because my guess is that in each webpart
// there are more than one <td> with a child element that has a class of .ms-vb2,
// but, if you could figure out a selector to specifically get the status cell:

var status = $("#WebPart td .ms-vb2").text();

if (status === "0 A - Contract Signed") {
    // do something
} else if (status === "Failed QA") {
    // do something else
} else if (status === "Contacted Dev") {
  // and now for something completely different
}
// etc

But, as you said in your edit/addition to your question, you are having difficulty uniquely identifying the elements you need to check. That's a bummer.

  • Thank you Dylan! That set me on the right track. Doing Traversals is a little out of my wheel house (I'm just self-teaching myself Javascript while on the job) so I ended up going with the length solution that you provided. I'm sure that I made my script way longer/more complex than it had to but it's currently working as intended so I think I'll leave it at that. I'll post my finished script in my original post for others to see. Thanks again! – onett199x 2 days ago
  • Another quick question for Extra Credit, Dylan... How do I check for multiple different Statuses? This formatting didn't seem to work: var $Text = $("td .ms-vb2:contains('Failed QA', 'Contacted Dev', 'Waiting on New Build', 'Failed Wrap QA', 'Graveyard')"); – onett199x 2 days ago
  • @onett199x updated my answer. – Dylan Cristy 2 days ago
  • Added my final edit with the final code that worked perfectly for me. Thank you again!! – onett199x 18 hours ago

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.