As an administrator, you may receive a requirement to add some logic to your Project Detail Pages (PDPs). There are some options how to do this. This is the first article of a series explaining ways to implement some logic using JavaScript/JQuery. All articles of this series apply to Project Online, Project Server 2013, Project Server 2016 and Project Server 2019.
There are three methods to get values of project fields:
Method | Advantage | Disadvantage |
Use only fields available on the page |
|
|
REST |
|
|
OData |
|
|
Due to the disadvantages of OData, I will skip this method. Moreover, nearly everything available with OData can be achieved with REST.
Following topics will be discussed in this and future articles:
General Preparation
To get the sample scripts to work you will need to download the following jQuery library: jquery-2.1.1.min.js. Other versions of this library may work but this was the one I used / tested with. Upload this library to your PWA site collection. I created a document library named "Scripts" to hold all scripts including this library. Modify and upload samples of these articles to the same library.
To apply a script to a PDP, open the PDP either from PWA Settings – Project Detail Pages. Open PDP for page editing.
Add a Content Editor web part to your page.
Edit the Content Editor web part.
Enter full qualified or relative path to your script. Set Layout to Hidden, users do not want to see this web part. To avoid empty space at the top, set Zone Index to (#WebPartsOnPage – 1) – in this sample two webparts, so the value is 1. Click OK to apply your changes.
Stop editing of PDP.
Now your script will be active on this Project Detail Page.
Show/hide a field depending on the value of a field on the same page
In this article, Enterprise Custom Field CostCenter will be hidden, if there are no cost for the project. Cost is an internal field, so in general GUID for this field is not known. So we need to look for the field name. If you look at the source of the page, you will see that all field information is provided in a table.
Skip details Unfortunately, this table has no table ID. In addition, the table rows holding the information have dynamic IDs. At least, the first part of the ID is dynamic and will be different in different sessions. Therefore, we will need to loop through all table rows to gather required data. Field names can be found in Header3 (<h3>). A table row for a field looks like the following:
- <tr id="ctl00_ctl33_g_ea2bd6d2_a61d_42a5_b607_f8deb28f50b2_ctl00_pfp_Repeater_ctl02_pfp_ContainingElem_3732199b917243a591b8eafff9e28f88_0">
Id of table row – will be used - <td nowrap="nowrap" valign="top" width="150px" class="ms-formlabel">
- <h3 class="ms-accentText">Cost</h3>
Field name in first column of table row, in tag h3 - <div class="ms-textXSmall"><span style="white-space:normal;"></span></div>
- </td>
- <td valign="top" width="500px" class="ms-formbody">
- <table width="100%" role="presentation">
Nested table in second column of table row - <tr>
- <td><div GUID="3732199b-9172-43a5-91b8-eafff9e28f88">$0.00</div></td>
Value of field in first column in only row of nested table - </tr>
- </table>
- </td>
- </tr>
Now take the information of the page and use it to hide field CostCenter.
<!-- Change path for jquery-2.1.1.min.js --> <script type="text/javascript"
src="/sites/blog/Scripts/jquery-2.1.1.min.js"></script> <script type="text/javascript">
//Extend for required languages, use all translations of used fields
//Sample: "Cost" in English, German and Dutch, Spanish (French "Coût"
will only work with some editors
var CostLanguages = ["Cost","Kosten","Costo"]
//Change to field to be hidden
var FieldToHideOnCost = "CostCenter"
$(document).ready(ExecuteOrDelayUntilScriptLoaded(MainFunction,
"sp.js"));
function MainFunction() {
//Use all table rows
var TRows = $("tr");
for (i = 0; i < TRows.length; i++){
//Field names in h3. No need to check other rows
if(TRows[i].getElementsByTagName('h3').length > 0){
//
if(jQuery.inArray(TRows[i].getElementsByTagName('h3')[0].innerText.replace('
* ',''),CostLanguages) > -1){
var CostFieldId = TRows[i].id
}
}
}
if(CostFieldId){
var CostCellContent = document.getElementById(CostFieldId);
var CostCellValue = CostCellContent.cells[1].innerText;
//If Cost = 0, we do not need to show "CostCenter". Unformat number,
Microsoft is using special formatting
if(LocalToNumber(CostCellValue,Sys.CultureInfo.CurrentCulture.numberFormat.CurrencyDecimalSeparator)
== 0){
setFieldVisibility(FieldToHideOnCost);
}
}
else {
console.log("Field not found")
}
}
//Hide a field
function setFieldVisibility(field) {
$(".ms-accentText").each(function (index) {
if ($(this).text() == field) {
$(this).closest('tr').toggle(false);
}
});
}
//Remove any number formatting by removing everything except decimal
separator and numbers
function LocalToNumber(NumberString,DecimalSeparator) {
var UnformattedNumber;
if (DecimalSeparator == ','){
UnformattedNumber = parseFloat(NumberString.replace(/[^0-9-,]/g, ''));
}
if (DecimalSeparator == '.'){
UnformattedNumber = parseFloat(NumberString.replace(/[^0-9-.]/g, ''));
}
return UnformattedNumber;
} </script> |
Copy above code into a text editor, modify at least the marked sections, save with file extension “js” or “html”, and upload to your script library.