Clarity

  • 1.  Use custom Javascript library in HTML portlet

    Posted Aug 29, 2017 03:40 AM

    Hi all,

    I need to use a custom library in html portlet in CA PPM.

     

    I placed the js file to: $NIKU_HOME/webroot/ui/ext folder

     

    and the html code for the portlet is like:

     

    <html>

    <head>
        <meta charset="utf-8"/>
         <script type="text/javascript" src="ui/ext/cytoscape.js"></script>
    </head>
    <style>
        #cy {
            width: 90%;
            height: 50%;
            position: absolute;
          background-color:red;
          border: 1px;
            top: 0;
            left: 0;

        }
    </style>


    <body>
        <div id="cy">Nejaky text</div>
        <script>
              var demoNodes = [];
            var demoEdges = [];
              
              function getCookie(c_name)
            {
                var i, cookieName, cookieValue, thisCookie, allCookies = document.cookie.split(";");
                for (i = 0; i < allCookies.length; i++)
                {
                    thisCookie = allCookies[i].split("=");
                    cookieName = thisCookie[0].replace(/^\s+|\s+$/g,"");
                    cookieValue = thisCookie[1];
                    //alert(cookieName);
                    //alert(cookieValue);
                    if (cookieName == c_name)
                    {
                        return unescape(cookieValue);
                    }
                }
            }
            function loadXMLDoc() {
                var xmlhttp;
                var xmlhttp = new XMLHttpRequest();
                xmlhttp.open("POST", endpoint, true);
                if (window.XMLHttpRequest) {
                    // code for IE7+, Firefox, Chrome, Opera, Safari
                    xmlhttp = new XMLHttpRequest();
                } else {
                    // code for IE6, IE5
                    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
                }

                xmlhttp.onreadystatechange = function() {
                    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {

                           var xmlDoc=xmlhttp.responseXML;
                             var parent_id=xmlDoc.getElementsByTagName("parent_id");
                        var parent_label=xmlDoc.getElementsByTagName("parent_label");
                             var child_id=xmlDoc.getElementsByTagName("child_id");
                             var child_label=xmlDoc.getElementsByTagName("child_label");
                             var parent_color=xmlDoc.getElementsByTagName("parent_color");
                        var child_color=xmlDoc.getElementsByTagName("child_color");
                           //alert(parent_id.length);
                           for (var i = 0; i < parent_id.length; i++) {                       
                            //alert(parent_id[i].nodeValue);
                            //alert(parent_label[i].childNodes[0].nodeValue);
                                  demoNodes.push({
                                data: {
                                    id: parent_id[i].childNodes[0].nodeValue,
                                    name:parent_label[i].childNodes[0].nodeValue,
                                    color: "'"+parent_color[i].childNodes[0].nodeValue+"'"
                                }
                            });
                                  demoEdges.push({
                                data: {
                                    source: parent_id[i].childNodes[0].nodeValue,
                                    target: child_id[i].childNodes[0].nodeValue
                                }
                            });
                        }
                    }
                }
                var nsql_id = 'c_q_prj_depend';
                var currentURL = window.location.toString();
                var endpoint = currentURL.substr(0, currentURL.indexOf("/niku")) + "/niku/xog";
                var sessionCookie = getCookie('sessionId');
               
                var xml = '' +
                '<se:Envelope xmlns:se="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q="http://www.niku.com/xog/Query">' +
                '<se:Header><q:Auth><q:SessionID>' + sessionCookie + '</q:SessionID></q:Auth></se:Header>' +
                '<se:Body><q:Query><q:Code>' + nsql_id + '</q:Code></q:Query></se:Body> ' +
                '</se:Envelope>';

                xmlhttp.open("POST", endpoint, true);
                xmlhttp.send(xml);
            }
            loadXMLDoc();
              
              var cy = cytoscape({
              container: document.getElementById('cy')
                /*,
              boxSelectionEnabled: false,
              autounselectify: true,

              style: cytoscape.stylesheet()
                .selector('node')
                    .css({
                        'content': 'data(name)',
                        'text-valign': 'center',
                        'text-halign': 'center',
                        'color': 'black',
                        'width': '250',
                        'border-width': 1,
                        'border-color': 'black',
                        'height': 40,
                        'font-size': 10,
                        'background-color': 'data(color)',
                        'shape': 'barrel',
                        'text-wrap': 'wrap'
                    })
              .selector('edge')
                    .css({
                        'curve-style': 'bezier',
                        'target-arrow-shape': 'triangle',
                        'width': 4,
                        'line-color': 'red',
                        'target-arrow-color': 'red'
                    })
              .selector(':selected')
                    .css({
                        'background-color': 'black',
                        'line-color': 'black',
                        'target-arrow-color': 'black',
                        'source-arrow-color': 'black',
                        'text-outline-color': 'black'
                    }),

             elements: {
                 nodes: demoNodes,
                 edges: demoEdges
              },
             
              layout: {
                  name: 'random',
                  padding: 10
              }*/

          });
              
        </script>

    </body>
    </html>

    Loading of the data works properly before adding row 100 and down.

     

    Could you please help me with solving this?

     

    Error message in Chrome Console is: 

    (ReferenceError): cytoscape is not defined--Client Side Exception
    com.google.gwt.core.client.JavaScriptException: (ReferenceError): cytoscape is not defined

     

    If I understood this well it means that the library is not loaded.

     

    Thank you all in advance,

    Martin



  • 2.  Re: Use custom Javascript library in HTML portlet

    Broadcom Employee
    Posted Aug 29, 2017 07:19 AM

    Note that this is not supported and might cause some unexpected issues. Please check:

    https://docops.ca.com/ca-ppm/15-2/en/reference/ca-ppm-studio-development/ca-ppm-studio-portlets#CAPPMStudioPortlets-html… 

    • Tips:

      • The primary purpose of HTML portlets is to display static data. 
      • Do not introduce your own embedded Javascript inside HTML portlets. The injection of custom code with redirected links or references to dynamic external resources is not supported.
      • Do not use the Javascript document.write command in HTML portlets.
      • Do not reload the current page, such as setting window.location.href in Javascript. CA PPM is a single-page Ajax-style application. Reloading the page is not optimal and can result in loss of application state data.
      • Always test and verify the compatibility of your CSS style names.

    I have seen issues on HTML portlets using Javascript. Even if you manage to make it work now, it can be broken after an upgrade so the development might not be future proof. Please take this into account when using the HTML portlets.

     

    Regards



  • 3.  Re: Use custom Javascript library in HTML portlet

    Posted Aug 29, 2017 01:02 PM

    To avoid these issues, one could always spin up another web application server (jetty for example or IIS if on an existing windows server) to process the request for a given HTML portlet.  If I need to execute some NSQL in context of the user, I pass in the sessionid otherwise I just use an API user account we have setup for supporting these types of extensions.

     

    I do this quite a bit since I need to some processing that isn't easy in JS.

     

    V/r,

    Gene



  • 4.  Re: Use custom Javascript library in HTML portlet

    Posted Aug 29, 2017 08:51 AM

    Hi Martin,

     

    Just had a quick read of your portlet html, I doubt access to that library is a problem. Check by navigating to

    MY_SERVER/niku/ui/ext/cytoscape.js

     

    I suspect it's data related, can you share the NSQL? (or at least the XML output it loops through?)

    If you haven't handled the data properly this is the sort of thing you'll see.  i.e. a NULL column at row 100 means no demoNodes

     

    Don't have the time to debug your javascript, but you could optimise that quite a bit 

     

    Andrew



  • 5.  Re: Use custom Javascript library in HTML portlet

    Posted Aug 29, 2017 12:35 PM

    The Clarity Content Filter might be filtering out your js file.

     

    I would place my js in a separate folder and update the Clarity Content Filter (in web.xml) to include that folder.

     

    V/r,

    Gene