aboutsummaryrefslogblamecommitdiffstats
path: root/data/lib/bugzillaDOMFunctions.js
blob: aedf131e01d5caa2a676a1fc2740bea95caef7c8 (plain) (tree)
1
2
3
4
5
6
7
8
9





                                                                        
  
                                                                       
  


               
  




































                                                                
  



                                                       
  


                                        
                                         







                                                     
                    



                                                   
  



                                                      







                                                                          
  



                                                          














                                                                           
  

                                   







                                           
  
                    
  
               

                                                                               






                                            
  







                                                                                  

                                                                               
  


                                                     
                                                                          


   

























                                                                            

                                                                             
  







                                                            






                                                                                

                                                    









































                                                                                
  






                                                                           
                                   
  






                                                       
                                                    
  







                                                                                   

                                                                              




















                                                     
                                       




                                          
































                                                                                         
                                               






                                                 

                                                         
  


                                                                              



                                                         
                             







                                                       
  










                                                                                 
  


                                                                          

















                                                        
  














                                                                
  


                           
                                               




                                                                               

                                         

                          









                                              
       

       







                                                                




                                                 



                          
  










                                                                 
  


                                                          
                               



                                                                             
  

                                                    











                                                            



















                                                     
// Released under the MIT/X11 license
// http://www.opensource.org/licenses/mit-license.php
"use strict";

/**
 * Select option with given value on the <SELECT> element with given id.
 *
 * Also execute change HTMLEvent, so that the form behaves accordingly.
 *
 * @param id
 * @param label
 * @return none
 *
 */
function selectOption (id, label, fireEvent) {
  if (!fireEvent) {
    fireEvent = true;
  }
  var sel = document.getElementById(id);
  sel.value = label;
  if (fireEvent) {
    var intEvent = document.createEvent("HTMLEvents");
    intEvent.initEvent("change", true, true);
    sel.dispatchEvent(intEvent);
  }
}

function selectOptionByLabel(id, label, fireEvent) {
  if (!fireEvent) {
    fireEvent = true;
  }
  var sel = document.getElementById(id);
  var labelRE = new RegExp(label.trim());
  var ourOption = Array.filter(sel.options, function (op) {
    return op.textContent.trim() === label;
  });

  if (ourOption[0]) {
    sel.value = ourOption[0].value;
  }

  if (fireEvent) {
    var intEvent = document.createEvent("HTMLEvents");
    intEvent.initEvent("change", true, true);
    sel.dispatchEvent(intEvent);
  }
}

/**
 * Add object to the text box (comment box or status whiteboard)
 *
 * @param id
 *          String with the id of the element
 * @param stuff
 *          String/Array to be added to the comment box
 *
 * @return none
 */
function addStuffToTextBox (id, stuff) {
  var saveFocus = document.activeElement;
  var textBox = document.getElementById(id);
  if (textBox.tagName.toLowerCase() === "textarea") {
    stuff = textBox.value ? "\n\n" + stuff : stuff;
    textBox.value += stuff;
  }
  else {
    textBox.value = addCSVValue(textBox.value,stuff);
  }
  saveFocus.focus();
}

/**
 * Remove a keyword from the element if it is there
 *
 * @param id
 *          String with the id of the element
 * @param stuff
 *          String/Array with keyword(s) to be removed
 */
function removeStuffFromTextBox (id, stuff) {
  var changedElement = document.getElementById(id);
  changedElement.value = removeCSVValue(changedElement.value,stuff);
}

/**
 * generalized hasKeyword ... search in the value of the box with given id
 *
 * @param id
 *          String with ID of the element we want to check
 * @param str
 *          String to be searched for
 * @return Boolean found?
 */
function idContainsWord (id, str) {
  var kwd = "";
  try {
    kwd = document.getElementById(id).value;
  } catch (e) {
    // For those who don't have particular element at all or if it is empty
    return false;
  }
  return (isInList(str, kwd.trim().split(/[,\s]+/)));
}

/**
 * Check for the presence of a keyword
 *
 * @param str
 *          String with the keyword
 * @return Boolean
 */
function hasKeyword (str) {
  return (idContainsWord('keywords', str));
}

/**
 * Set the bug to NEEDINFO state
 *
 * Working function.
 *
 * @return none
 * @todo TODO we may extend this to general setNeedinfo function with parameter
 *       [reporter|assignee|general-email-address]
 */
function setNeedinfoReporter () {
  clickMouse("needinfo");
  selectOption("needinfo_role", "reporter");
}

/**
 *
 */
function getOwner () {
  // TODO(maemo) doesn't work on maemo
  var assigneeAElement = getOptionTableCell("bz_show_bug_column_1","Assigned To");
  return parseMailto(assigneeAElement);
}

/**
 * Return maintainer which is per default by bugzilla (which is not necessarily
 * the one who is default maintainer per component)
 *
 * @return String with the maintainer's email address
 */
function getDefaultBugzillaMaintainer (component) {
  return filterByRegexp(constantData.defBugzillaMaintainerArr, component);
}

/**
 * dd
 *
 * @return Element with the href attribute containng the information
 */
function getOptionTableCell(tableId, label) {
  var cleanLabelRE = new RegExp("^\\s*([^.:]*):?\\s*$");
  label = label.trim().replace(cleanLabelRE,"$1").toLowerCase();

  var rows = document.getElementById(tableId).getElementsByTagName("tr");
  var ourLine = Array.filter(rows, function(row) {
    var curLabelElems = row.getElementsByTagName("td");
    if (curLabelElems.length > 0) {
      var curLabel = curLabelElems[0].textContent.toLowerCase();
      curLabel = curLabel.replace(cleanLabelRE,"$1");
      return (curLabel === label); // maybe this could be a RE match instead
    }
  });

  if (ourLine.length > 0) {
    return ourLine[0].getElementsByTagName("td")[1].
    getElementsByTagName("a")[0];
  }
  return null;
}

/**
 * Generic function to add new button to the page. Actually copies new button
 * from the old one (in order to have the same look-and-feel, etc.
 *
 * @param location
 *          Object around which the new button will be added
 * @param after
 *          Boolean before or after location ?
 * @param pkg
 *          String which package to take the command from
 * @param id
 *          String which command to take
 * @return none
 */
function createNewButton (location, after, cmdObj) {
  try {
    var newId = cmdObj.name.toLowerCase().replace(/[^a-z0-9]+/,"","g") + "_btn";
  } catch (e) {
    console.error("createNewButton : e = " + e +
        "\ncreateNewButton : cmdObj.toSource() = " +
        cmdObj.toSource());
  }

  // protection against double-firings
  if (document.getElementById(newId)) {
    console.log("Element with id " + newId + " already exists!");
    return ;
  }

  var newButton = document.createElement("input");
  newButton.setAttribute("id", newId);
  newButton.setAttribute("type", "button");
  newButton.value = cmdObj.name;
  newButton.addEventListener("click", function(evt) {
    executeCommand(cmdObj);
  }, false);

  var originalLocation = document.getElementById(location);

  try {
    if (after) {
      originalLocation.parentNode.insertBefore(newButton,
          originalLocation.nextSibling);
      originalLocation.parentNode.insertBefore(document
          .createTextNode("\u00A0"), newButton);
    }
    else {
      originalLocation.parentNode.insertBefore(newButton, originalLocation);
      originalLocation.parentNode.insertBefore(document
          .createTextNode("\u00A0"), originalLocation);
    }
  } catch (e) {
    if (e instanceof TypeError) {
      console.error("cannot find originalLocation element with id " + location);
    }
    else {
      throw e;
    }
  }
}

/**
 * Get the current title of the bug
 *
 * @return string
 */
function getSummary() {
  return document.getElementById("short_desc_nonedit_display").textContent;
}

/**
 * Get the current title of the bug
 *
 * @return string
 */
function getSeverity() {
  return document.getElementById("bug_severity").value;
}

/**
 * Get the current email of the reporter of the bug.
 *
 * @return string
 */
function getReporter () {
  var reporterElement = getOptionTableCell("bz_show_bug_column_2", "Reported");
  // RH Bugzilla after upgrade to 3.6.2 moved the information to other column
  if (!reporterElement) {
    reporterElement = getOptionTableCell("bz_show_bug_column_1", "Reported", true);
  }
  // Maemo calls the label "Reporter" and it doesn't have ids on table columns
  // ... TODO(maemo)
  return parseMailto(reporterElement);
}

function getComponent() {
  var elem = document.getElementById("component");
  if (elem) {
    return elem.value;
  }
  return null;
}

function getProduct() {
  var elem = document.getElementById("product");
  if (elem) {
    return elem.value;
  }
  return null;
}

function commentsWalker (fce) {
  var comments = document.getElementById("comments").
  getElementsByClassName("bz_comment");
  Array.forEach(comments, function(item) {
    fce(item);
  });
}


/**
 * Parse the row with the attachment
 *
 * @param DOM
 *          element to be parsed
 * @return array with string name of the attachment, integer its id number,
 *         string of MIME type, integer of size in kilobytes, and the whole
 *         element itself
 *
 * TODO error handling is missing ... it's bleee
 */
function parseAttachmentLine(inElem) {
  var MIMEtype = "";
  var size = 0;

  // Skip over obsolete attachments
  if (inElem.getElementsByClassName("bz_obsolete").length > 0) {
    return ([]);
  }

  // getting name of the attachment
  var attName = inElem.getElementsByTagName("b")[0].textContent.trim();

  // TODO probably could use url.URL object
  var aHrefsArr = inElem.getElementsByTagName("a");
  var aHref = Array.filter(aHrefsArr, function(x) {
    return x.textContent.trim() === "Details";
  })[0];
  var id = parseURL(aHref.getAttribute("href")).params.id;

  // getting MIME type and size
  var stringArray = inElem.getElementsByClassName("bz_attach_extra_info")[0].textContent.
  replace(/[\n ()]+/g, " ").trim().split(", ");
  size = parseInt(stringArray[0], 10);
  MIMEtype = stringArray[1].split(" ")[0];

  return [ attName, id, MIMEtype, size, inElem ];
}


/**
 * collect the list of attachments in a structured format
 *
 * @return Array of arrays, one for each attachments; each record has string
 *         name of the attachment, integer its id number, string of MIME type,
 *         integer of size in kilobytes, and the whole element itself
 */
function getAttachments () {
  var outAtts = [];
  var atts = document.getElementById("attachment_table").
  getElementsByTagName("tr");
  for ( var i = 1, ii = atts.length - 1; i < ii; i++) {
    outAtts.push(parseAttachmentLine(atts[i]));
  }
  return outAtts;
}

/**
 * Get login of the currently logged-in user.
 *
 * @return String with the login name of the currently logged-in user
 */
function getLogin () {
  var lastLIElement = document.querySelector("#header ul.links li:last-of-type");
  var loginArr = lastLIElement.textContent.split("\n");
  var loginStr = loginArr[loginArr.length - 1].trim();
  return loginStr;
}

/**
 * adds a person to the CC list, if it isn't already there
 *
 * @param who
 *          String with email address or "self" if the current user of the
 *          bugzilla should be added
 */
function addToCCList (who) {
  if (!who) {
    return ;
  }
  if (who === "self") {
    document.getElementById("addselfcc").checked = true;
  }
  else {
    clickMouse("cc_edit_area_showhide");
    if (!isInList(who, getCCList())) {
      addStuffToTextBox("newcc",who);
    }
  }
}

/**
 * a collect a list of emails on CC list
 *
 * @return Array with email addresses as Strings.
 */
function getCCList () {
  var CCListSelect = document.getElementById("cc");
  var outCCList = [];
  if (CCListSelect) {
    outCCList = Array.map(CCListSelect.options, function(item) {
      return item.value;
    });
  }
  return outCCList;
}

/**
 * remove elements from the page based on their IDs
 *
 * @param doc
 *          Document object
 * @param target
 *          Array with querySelector parameters
 * @param remove
 *          Boolean indicating whether the node should be actually removed or
 *          just hidden.
 * @return none TODO remove parameter could be replaced by function which would
 *         do actual activity.
 */
function killNodes(doc, target, remove) {
  var victimElements = [];

  if (target.forEach) {
    target.forEach(function(x) {
      var targetNode = doc.querySelector(x);
      if (targetNode) {
        if (remove) {
          victimElements.push([x,targetNode]);
        }
        else {
          targetNode.style.display = "none";
        }
      }
    });
  }

  var elem = {};
  // Don't run victimElements.forEach here as we are effectively
  // removing its members.
  for(var i = 0, ii = victimElements.length; i < ii; i++) {
    elem = victimElements[i];
    try {
      elem[1].parentNode.removeChild(elem[1]);
    }
    catch (e if e instanceof TypeError) {
      console.error("Cannot remove: " + elem[0]);
    }
  }
}

/**
 * Is this bug a RHEL bug?
 *
 * @return Boolean true if it is a RHEL bug
 */
function isEnterprise() {
  var result = ProfessionalProducts.some(function(elem,idx,arr) {
    return new RegExp(elem).test(getProduct());
  });
  return result;
}

/**
 * Find out whether the bug is needed an attention of bugZappers
 *
 * @return Boolean whether the bug has been triaged or not
 */
function isTriaged() {
  return hasKeyword("Triaged");
}

/**
 * Return string with the ID for the external_id SELECT for external bugzilla
 *
 * @param URLhostname
 *          String hostname of the external bugzilla
 * @return String with the string for the external_id SELECT
 */
function getBugzillaName(URLhostname, bzLabelNames) {
  var bugzillaID = "";
  if (bzLabelNames[URLhostname]) {
    bugzillaID = bzLabelNames[URLhostname];
  }
  else {
    bugzillaID = "";
  }
  return bugzillaID;
}

/**
 *
 * original 2011-03-30 15:49:27 EDT
 */
function parseBZCommentDate(dateString) {
  var tZone = {
    "EDT": 4,
    "EST": 5
  };

  var dateArr = dateString.trim().split(/\s+/);
  var timeZoneOffset = tZone[dateArr[2]] -
    ((new Date()).getTimezoneOffset())/60;
  var dArr = dateArr[0].split("-");
  var tArr = dateArr[1].split(":");
  var dayObj = new Date(+dArr[0],+dArr[1]-1,+dArr[2],
    +tArr[0]+timeZoneOffset,+tArr[1],+tArr[2],0);
  return dayObj;
};