Ricardo / Ideare plus

// File encoding: UTF-8
//{
// This is a script for the Ideare / Embrapa site.
//
// Copyright (c) 2015-2016, Ricardo Mendonça Ferreira (ric@mpcnet.com.br)
// Released under the GPL license - http://www.gnu.org/copyleft/gpl.html
//
// --------------------------------------------------------------------
//
// ==UserScript==
// @name          Ideare plus
// @description   Pequenas melhorias do ideare, como matriz lógica
// @namespace     https://openuserjs.org/scripts/Ricardo/
// @homepageURL   https://openuserjs.org/scripts/Ricardo/Ideare_plus
// @copyright     2015, Ricardo Mendonca Ferreira
// @license       GPL v3; http://www.gnu.org/copyleft/gpl.html
// @oujs:author   Ricardo
// @author        Ricardo Mendonça Ferreira <ric@mpcnet.com.br> https://openuserjs.org/scripts/Ricardo/
// @include       http://sistemas.sede.embrapa.br/ideare/pages/relatorios/formatoimpressaosubmissao/FormatoImpressaoSubmissao.jsf
// @include       https://sistemas.sede.embrapa.br/ideare/pages/relatorios/formatoimpressaosubmissao/FormatoImpressaoSubmissao.jsf
// @match         http://sistemas.sede.embrapa.br/ideare/pages/relatorios/formatoimpressaosubmissao/FormatoImpressaoSubmissao.jsf
// @match         https://sistemas.sede.embrapa.br/ideare/pages/relatorios/formatoimpressaosubmissao/FormatoImpressaoSubmissao.jsf
// @grant         none
// @version       0.02
// ==/UserScript==
//
// History:
// --------
// 2016.01.20  [0.02] Now works on Firefox, too.
// 2015.09.09  [0.01] First tests.
//
//}

(function() {

   function xpath(xpathExpression, contextNode) {
      if (contextNode == null)
         contextNode = document;
      namespaceResolver = null;
      resultType        = XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE;
      result            = null;
      return document.evaluate(xpathExpression, contextNode,
                               namespaceResolver, resultType, result);
   }

   function findByTagAndText(tag, text, source) {
      if (source == null) source = document;
      var elems = source.getElementsByTagName(tag);
      var r = [];
      for (var i = 0; i < elems.length; i++)
         if (elems[i].textContent == text)
            r.push(elems[i]);
      return r;
   }

   function findByTagWithText(tag, text, source) {
      if (source == null) source = document;
      var elems = source.getElementsByTagName(tag);
      var r = [];
      for (var i = 0; i < elems.length; i++)
         if (elems[i].textContent.indexOf(text) != -1)
            r.push(elems[i]);
      return r;
   }

   function openWindow(title, w, h, html) {
      w = window.open('', title, 'width='+w+',height='+h+",scrollbars=yes");
      // w.document.open();
      // w.document.write(html); // Fails on Firefox!
      w.document.body.innerHTML = html;
      // w.document.close();
   }

   function htmlReport(og, oe, planos) {
      // HTML report
      var css  = '<style type="text/css">body { font-family: Arial, Helvetica, sans-serif; } table.td { font-family: Arial, Helvetica, sans-serif; }</style>\n';
      var html = "<html><head><title>Matriz Lógica</title>"+css+"</head><body><table border=1>\n";
      html += "<tr><th>Objetivo geral</th><th>Objetivos específicos</th><th>Planos de ação</th><th>Atividades</th><th>Resultados</th><th>Tipo resultado</th><th>Ano previsão</th></tr>\n";

      // Find out number of rows
      var nrt = 0;
      for (var p = 0; p < planos.length; p++)
         nrt += Math.max(planos[p].atividades.length, planos[p].resultados.length);

      // Create table rows
      var rn = 0;
      for (var p = 0; p < planos.length; p++) {
         plano = planos[p];
         nr = Math.max(plano.atividades.length, plano.resultados.length);
         for (r = 0; r < nr; r++) {
            var c1 = c2 = c3 = c4 = c5 = c6 = c7 = "";
            if (rn === 0) c1 = "<td rowspan="+nrt+">"+og+"</td>";
            rn++;
            if (r === 0) c2 = "<td rowspan="+nr+">"+oe.pop()+"</td>";            
            if (r === 0) c3 = "<td rowspan="+nr+">"+plano.nome+"</td>";
            if (plano.atividades.length) c4 = "<td>"+plano.atividades.pop()+"</td>";
            if (plano.resultados.length) {
               var res = plano.resultados.pop();
               c5 = "<td>"+res.titulo+"</td>";
               c6 = "<td>"+res.tipo+"</td>";
               c7 = "<td>"+res.ano+"</td>";
            }

            html += "<tr>"+c1+c2+c3+c4+c5+c6+c7+"</tr>\n";
         }
      }
      html += "</table></body></html>";
      //html = html.replace(/<td/g, '<td style="vertical-align:middle"'); // no effect on LibreOffice?
      html = html.replace(/<td/g, '<td valign="middle"'); // no effect on LibreOffice?
      openWindow("matriz_logica", 700, 500, html);
      //alert("Let's do it!\n"+og);
   }

   function matrizLogica() {
      // Harvest data from the webpage "Visualização da Submissão"
      // then generate HTML report

      // 1st, check if SELECIONAR TODOS is selected
      var cb = document.getElementById("principal:chkTodos");
      if (!cb.checked) {
          alert("Por favor, marque a opção 'SELECIONAR TODOS' e clique 'Consultar'");
          return false;
      }

      var td;

      // Get "Objetivo Geral" (string)
      td = findByTagAndText("td", "Objetivo Geral:");
      var og = td[0].nextElementSibling.textContent;

      // Get "Objetivos Específicos" (array of strings)
      // Problem: it is unordered!
      td = findByTagAndText("td", "Objetivos Específicos:");
      td = td[0].nextElementSibling.getElementsByTagName("td");
      var oe = [];
      for (var i = 1; i < td.length; i += 2)
         oe.push(td[i].textContent);

      // Get "Plano de Ação" and each respective "Atividade"
      // planos[i].nome      : string
      // planos[i].atividades: array of strings
      td = findByTagAndText("td", "Plano de Ação:");
      var planos = [];
      for (var p = 1; p < td.length; p++) {
         var pa = td[p].nextElementSibling.textContent; // string with "plano de ação"
         // Atividades
         var atvsn = []; // array to be filled with strings
         var atvs  = td[p].parentNode.parentNode.parentNode.nextSiblings()[0];
         atvs = findByTagAndText("td", "Atividade:", atvs);
         for (var i = 0; i < atvs.length; i ++)
            atvsn.push(atvs[i].nextElementSibling.textContent);
         // save data in the object
         planos.push({"nome":pa, "atividades":atvsn, "resultados":[]});
      }
      
      // Get "Resultados"
      td = findByTagWithText("td", "Vinculado ao Plano de Ação:");
      for (var i = 0; i < td.length; i++) {
         if (td[i].childElementCount == 2) {
            var pa   = td[i].childElements()[1].textContent;
            var rows = td[i].parentNode.siblings();
            var tipo = rows[1].getElementsByTagName("span")[1].textContent;
            var titu = rows[2].getElementsByTagName("span")[1].textContent;
          //var desc = rows[3].getElementsByTagName("span")[1].textContent;
            var ano  = rows[4].getElementsByTagName("span")[1].textContent;
            for (var p = 0; p < planos.length; p++)
               if (planos[p].nome == pa)
                  planos[p].resultados.push({"titulo": titu, "tipo": tipo, "ano": ano});
         }
      }

      htmlReport(og, oe, planos);//return [og, oe, planos];//planos = matrizLogica(); og=planos[0]; oe=planos[1]; planos=planos[2];
      return false;
   }

   // Find the "print" button
   var results = xpath("//input[@value='Imprimir']");
   if (results.snapshotLength != 1) {
      alert("Não achei o botão de impressão - talvez seja preciso alterar este script...");
   } else {
      var btPrint = results.snapshotItem(0);

      // Create & add our button
      var b = document.createElement('button');
      b.type          = "button";
      b.name          = "matrizLogica";
      b.textContent   = "Matriz Lógica";
      b.title         = "Marque a opção 'SELECIONAR TODOS', clique 'Consultar' e clique aqui para criar a matriz lógica.";
      b.addEventListener('click', matrizLogica, false);
      btPrint.parentElement.appendChild(b);
   }

})();