Project Insight Report Forms With JavaScript (Advanced Tutorial)

Please note that these examples may vary case by case.

Requirements: Knowledge of Custom Item types in Project Insight, experience with JavaScript, HTML, CSS, and programming concepts and practices in general.
An updated browser that can support the latest W3C specifications such as: HTML5, CSS3 and other scripting languages and extensions.

This tutorial uses the latest version of Google Chrome.

To customize a Project Insight Report (Project, Task, Issue, etc.), you will first need to 'Enable Editing Directly On Forms', which is an option setting within the Culture & Interface Labels under the Project Insight Administration settings.

Enable Editing Directly On Forms
Figure 1 - Enable Editing Directly On Forms.
Tip: Select the appropriate setting for your environment or you can choose to have this functionality globally (System Level).

Once you have enabled the option to allow forms editing, click on the global report icon and either load an existing saved report or load a new report.

Load Report Form

Figure 2 - Load A Report Form (In this example, we load the Task Report).

We want to edit this form to add javascript to the report. To do this, click on the Show Additional Editable Text link at the bottom of the web form.

Edit the form
Figure 3 - Click the Show Additional Editable Text link to expose the forms properties and advanced features.

The window that loads is the "Form Options and Advanced Settings". Here, we can specify actions and change settings. For example, we can edit the current form by applying JavaScript.

Form options and advanced settings
Figure 4 - Edit 'this' form only to include custom JavaScript.
Tip: You can implement the JavaScript for all forms within Project Insight or target just the single form. Caution when using the global "All" option because it will apply the script throughout Project Insight and may cause errors/bugs.

In the Form Text box control, you can apply your JavaScript to fire off when the form loads.

Form textarea box
Figure 5 - Apply your JavaScript in the Form Text control, which will fire off your script during the forms page cycle event.

This particular example will focus on calculating two Project Insight task fields and setting a custom field with the calculated value at run-time. To learn more about how to create custom fields, please visit this article: User Defined Fields & Forms (Custom Items) With JavaScript

Task report fields calculated
Figure 6 - Calculating Project Insight task fields and setting a custom field with the value.
Tip: This tutorial assumes as a user, you know how to setup and create custom fields, otherwise, please click the related links for more info. Creating Custom Fields, User Defined Fields & Forms (Custom Items) With JavaScript

Below is an example of how to best access data within the report form headers, rows and cells. If you have followed previous tutorials and are comfortable using custom fields and JavaScript then you'll be able to get/set values using jQuery.

JavaScript code snippet for report forms
Figure 6 - Code snippet to get/set form fields within a Project Insight report form using variables and other jQuery methods.
Tip: Set your custom field name and other field selectors (ID's or class names) to a local or global variables.
Example: You can have this function perform during the page load only or during an action/event from a specific control or the page itself (see full code snippet).

Full code snippet template. Please modify to reflect against your test environment!

//Specify a function to execute when the DOM is fully loaded.
$(function() {
    //Perform first function when the page loads
    preCalculateMarkupPercentage();
    //Perform the recalucations if the form reloads due to an AJAX call
    $("#A_runReportActiono_Item_0").on('click', this, function() {
        //Need to call the function on every load
        setTimeout(function() {
            //Code to call
            preCalculateMarkupPercentage();
        }, 6000);//set to 6 second delay due to larger data sets
    });
});
var workBillableExpenseColIndex = 0;
var workExpenseColIndex = 0;
var markupPercentColIndex = 0;
var markupPercentColName = 'cs_CustomField13';
var lastRowIndex = $("#t tr").length;
//This function finds and sets the values before calucations
function preCalculateMarkupPercentage() {
    $('#t th').each(function() {
        var thId = $(this).attr("id");
        if (thId == 'cs_WorkTotalExpenseBillable') {
            workBillableExpenseColIndex = $(this).index();
        }
        if (thId == 'cs_WorkTotalExpense') {
            workExpenseColIndex = $(this).index();
        }
        //Change to custom field # referenced when creating
        if (thId == markupPercentColName) {
            markupPercentColIndex = $(this).index();
        }
    });
    var workBillableExpenseVal = 0;
    var workExpenseVal = 0;
    var markupPercentTD;
    $("#t td").each(function(index) {
        if ((lastRowIndex - 1) != $(this).closest('tr')[0].sectionRowIndex) {
            if ($(this).index() == workBillableExpenseColIndex) {
                workBillableExpenseVal = $(this).text();
            }
            if ($(this).index() == workExpenseColIndex) {
                workExpenseVal = $(this).text();
            }
            if ($(this).index() == markupPercentColIndex) {
                $(this).addClass('AR')
                markupPercentTD = $(this);
                calculateMarkupPercentage(workBillableExpenseVal, workExpenseVal, markupPercentTD)
            }
        }
    });
}
function calculateMarkupPercentage(wbeVal, weVal, markupPercentCFElement) {
    wbeVal = wbeVal.replace(/[$,]+/g, "");
    weVal = weVal.replace(/[$,]+/g, "");
    var markupPercentVal = parseFloat((wbeVal - weVal) / parseFloat(wbeVal));
    if (!isNaN(markupPercentVal)) {
        $(markupPercentCFElement).text(parseFloat(markupPercentVal * 100).toFixed(1) + '%');
    }
};

You can add a comment below to start a dialog on this topic. Others who find this article may benefit from your questions too.


Online 4/7/2016