function collectQuestions() {
    var questions = findChildNodesByType(document.body, "question");
    var res = "<q>";

    for (var i = 0; i < questions.length; i++) {
        var q = questions[i];
        var qId = q.id;

        var flashField = document.getElementById("answerField" + qId);
        if (flashField != null) {
            if (flashField.value != "") { // flash question is left unanswered
                res += flashField.value;
            } else {
                res += "<r t=\"" + q.getAttribute("answerType") + "\" id=\"" + q.id + "\"></r>";
            }
        } else {
            res += collectAnswers(q);
        }
    }

    res += "</q>";
    return res;
}

function collectAnswers(question) {
  var type = question.getAttribute("answerType");
  var res = "<r t=\"" + type + "\" id=\"" + question.id + "\" " + collectDontKnow(question.previousSibling) + " " + collectNoneOfThese(question.previousSibling) + " >";
  if (type == "checkboxes") {
    res += collectCheckboxes(question.previousSibling);
  }
  else if (type == "radiogroup") {
    res += collectRadiogroup(question.previousSibling);
  }
  else if (type == "yesnoitem") {
    res += collectYesnoitem(question.previousSibling);
  }
  else if (type == "numeric") {
    res += collectNumeric(question.previousSibling);
  }
  else if (type == "opentext") {
    res += collectOpentext(question.previousSibling);
  }
  else if (type == "textarea") {
    res += collectTextarea(question.previousSibling);
  }
  else if (type == "combobox") {
    res += collectCombobox(question.previousSibling);
  }
  else if (type == "ranking") {
    res += collectRanking(question.previousSibling);
  }
  else if (type == "dragndrop"){
      res += collectDragnDrop(question.previousSibling);
  }
  else if (type == "matrix") {
    res += collectMatrix(question);
  }
  res += "</r>";
  return res;
}

function collectDontKnow(question) {
  function collectDontKnowItem(item) {
    item = item.previousSibling;

    while (item.nodeType != 1) {
      item = item.previousSibling;
    }      
    var answer = item;
    if (answer.getAttribute('customElement') == 'true') {
        answer = answer.getElementsByTagName('table')[0];
    }

    var res = "dK=\"" + isChecked(answer) + "\" ";

    var optionals = findChildNodesByType(item.parentNode.parentNode.parentNode, "custom");
    if (optionals.length == 0) {
      res += " dKT=\"\"";
    }
    else {
      var optional = optionals[0].previousSibling;
      while (optional.nodeType != 1) {
        optional = optional.previousSibling;
      }

      res += " dKT=\"";

      var controls = optional.parentNode.getElementsByTagName('INPUT');
      for (var i = 0; i < controls.length; i++) {
        if (i > 0) {
          res += "\u02DB";
        }

        res += htmlEscape(controls[i].value);
      }
      res += "\"";
    }

    return res;
  }

  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var dontKnows = findChildNodesByType(question, "dontKnow");
  var res = "";
  if (dontKnows.length > 0) {
    res = collectDontKnowItem(dontKnows[0]);
  }

  return res;
}

function collectNoneOfThese(question) {
  function collectNoneOfTheseItem(item) {
    item = item.previousSibling;

    while (item.nodeType != 1) {
      item = item.previousSibling;
    }
    var answer = item;
    if (answer.getAttribute('customElement') == 'true') {
        answer = answer.getElementsByTagName('table')[0];
    }

    var res = "nOT=\"" + isChecked(answer) + "\" ";

    var optionals = findChildNodesByType(item.parentNode.parentNode.parentNode, "custom");
    if (optionals.length == 0) {
      res += " nOTT=\"\"";
    }
    else {
      var optional = optionals[0].previousSibling;
      while (optional.nodeType != 1) {
        optional = optional.previousSibling;
      }

      res += " nOTT=\"";

      var controls = optional.parentNode.getElementsByTagName('INPUT');
      for (var i = 0; i < controls.length; i++) {
        if (i > 0) {
          res += "\u02DB";
        }

        res += htmlEscape(controls[i].value);
      }
      res += "\"";
    }

    return res;
  }

  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var noneOfThese = findChildNodesByType(question, "noneOfThese");
  var res = "";
  if (noneOfThese.length > 0) {
    res = collectNoneOfTheseItem(noneOfThese[0]);
  }

  return res;
}

function collectDragnDrop(question){

    while (question.nodeType != 1) {
      question = question.previousSibling;
    }
    
    var answerNodes = findChildNodesByType(question, 'answer');
    var availableAnswersNode = findChildNodeByType(question, 'availableAnswers');
    var availableAnswerNodes = findChildNodesByType(availableAnswersNode, 'availableAnswer');
    var res = "";
    var j = 0;
    for (var i = 0; i < answerNodes.length; i++){
        var availableAnswer = findChildNodeByType(answerNodes[i], 'availableAnswer');
        if (availableAnswer){
            res += "<a v=\"" + answerNodes[i].getAttribute('value') + "\" c=\"" + availableAnswer.getAttribute('answerPrefix') + "\" />";
        } else {
            res += "<a v=\"\" c=\"" + availableAnswerNodes[j].getAttribute('answerPrefix') + "\" />";
            j++;
        }
    }
    for (var k = j; k < availableAnswerNodes.length; k++){
        res += "<a v=\"\" c=\"" + availableAnswerNodes[k].getAttribute('answerPrefix') + "\" />";
    }
    return res;
}

function collectCheckboxes(question) {
  function collectAnswer(answer) {
    var code = answer.getAttribute("answerPrefix");
    answer = answer.previousSibling;

    while (answer.nodeType != 1) {
      answer = answer.previousSibling;
    }
    var item = answer;
    if (item.getAttribute('customElement') == 'true') {
        item = item.getElementsByTagName('table')[0];
    }

    var res = "<a c=\"" + code + "\" v=\"" + isChecked(item) + "\"";

    var optionals = findChildNodes(answer.parentNode.parentNode, 
            function(o) {return (o.getAttribute("mcfType") == "custom" && o.getAttribute("answerPrefix") == code)});

    if (optionals.length > 0) {
      var optional = optionals[0].previousSibling;
      while (optional.nodeType != 1) {
        optional = optional.previousSibling;
      }

      res += " o=\"";
      var controls = optional.parentNode.getElementsByTagName('INPUT');
      for (var i = 0; i < controls.length; i++) {
        if (i > 0) {
          res += "\u02DB";
        }

        res += htmlEscape(controls[i].value);
      }

      res += "\"";
    }

    res += "/>";
    return res;
  }

  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var answers = findChildNodesByType(question, "answer");
  var res = "";
  for (var i = 0; i < answers.length; i++) {
    res += collectAnswer(answers[i]);
  }

  return res;
}

function collectRadiogroup(question) {
  return collectCheckboxes(question);
}

function collectYesnoitem(question) {
  return collectCheckboxes(question);
}

function collectNumeric(question) {
  function collectOptional(area) {
    var optionals = findChildNodesByType(area, "custom");
    if (optionals.length > 0) {
      var res = "";
      var optional = optionals[0].previousSibling;
      while (optional.nodeType != 1) {
        optional = optional.previousSibling;
      }

      var controls = optional.parentNode.getElementsByTagName('INPUT');
      for (var i = 0; i < controls.length; i++) {
        if (i > 0) {
          res += "\u02DB";
        }

        res += controls[i].value;
      }
      return "o=\"" + htmlEscape(res) + "\"";
    }
    return null;
  }

  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var answers = findChildNodesByType(question, "answer");
  var res = "";
  for (var i = 0; i < answers.length; i++) {
    var prefix = answers[i].getAttribute("answerPrefix");
    var answer = answers[i].previousSibling;
    while (answer.nodeType != 1) {
      answer = answer.previousSibling;
    }

    var optional = collectOptional(answer.parentNode);
    res += ("<a v=\"" + htmlEscape(answer.value) + "\" " + (optional != null ? optional : "") + " c=\"" + htmlEscape(prefix) + "\" />");
  }

  return res;
}

function collectOpentext(question) {
  return collectNumeric(question);
}

function collectTextarea(question) {
  return collectNumeric(question);
}

function collectCombobox(question) {
  return collectNumeric(question);
}

function collectRanking(question) {
  return collectNumeric(question);
}

function collectMatrix(question) {
  var subType = question.getAttribute("subType");
  if ((subType == "single") || (subType == "singlePerLine")
          || subType == "singlePerLineAndColumn" || subType == "several"
          || subType == "singlePerColumn") {
    return collectCheckboxes(question.previousSibling);
  }
  else {
    return collectNumeric(question.previousSibling);
  }
}

function subscribeQuestions() {
  var questions = findChildNodesByType(document.body, "question");
  for (var i = 0; i < questions.length; i++) {
    subscribeQuestion(questions[i]);
  }
}

function subscribeQuestion(question) {
  var type = question.getAttribute("answerType");
  var questionGuid = '' + question.id;

  subscribeDontKnow(question.previousSibling, questionGuid);
  subscribeNoneOfThese(question.previousSibling, questionGuid);

  if (type == "checkboxes") {
    subscribeCheckboxes(question.previousSibling);
  }
  else if (type == "radiogroup") {
    subscribeRadiogroup(question.previousSibling);
  }
  else if (type == "yesnoitem") {
    subscribeYesnoitem(question.previousSibling);
  }
  else if (type == "numeric") {
    subscribeNumeric(question.previousSibling);
  }
  else if (type == "opentext") {
    subscribeOpentext(question.previousSibling);
  }
  else if (type == "textarea") {
    subscribeTextarea(question.previousSibling);
  }
  else if (type == "combobox") {
    subscribeCombobox(question.previousSibling);
  }
  else if (type == "ranking") {
    subscribeRanking(question.previousSibling);
  }
  else if (type == "matrix") {
    subscribeMatrix(question);
  }
  else if (type == "dragndrop") {
      subscribeDragnDrop();
  }
}

function subscribeDragnDrop(question){

}

function subscribeDontKnow(question, questionGuid) {
  function subscribeDontKnowItem(item, question) {
    item = item.previousSibling;

    while (item.nodeType != 1) {
      item = item.previousSibling;
    }

    if (item.getAttribute('customElement') == 'true') {
        item = item.getElementsByTagName('table')[0];
    }

    var id = item.id + "_optional";
    item.highNode = question;
    item.onclick = function() {
      if (isChecked(this)) {
        if (this.questionObject){
            this.questionObject.resetQuestions();
        } else {
            resetQuestion(this.highNode, questionGuid);
        }
        resetNoneOfThese(this.highNode);
      }
    }
    item = null;
  }

  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  resetDontKnow(question);
  var dontKnows = findChildNodesByType(question, "dontKnow");
  if (dontKnows.length > 0) {
    subscribeDontKnowItem(dontKnows[0], question);
  }
}

function subscribeNoneOfThese(question, questionGuid) {
  function subscribeNoneOfTheseItem(item, question) {
    item = item.previousSibling;

    while (item.nodeType != 1) {
      item = item.previousSibling;
    }

    if (item.getAttribute('customElement') == 'true') {
        item = item.getElementsByTagName('table')[0];
    }

    var id = item.id + "_optional";
    item.highNode = question;
    item.onclick = function() {
      if (isChecked(this)) {
        if (this.questionObject){
            this.questionObject.resetQuestions();
        } else {
            resetQuestion(this.highNode, questionGuid);
        }
        resetDontKnow(this.highNode);
      }
    }
    item = null;
  }

  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  resetNoneOfThese(question);
  var noneOfThese = findChildNodesByType(question, "noneOfThese");
  if (noneOfThese.length > 0) {
    subscribeNoneOfTheseItem(noneOfThese[0], question);
  }
}

function resetQuestion(question, questionGuid) {
  var answers = findChildNodesByType(question, "answer");
  for (var i = 0; i < answers.length; i++) {
    answers[i] = answers[i].previousSibling;
    while (answers[i].nodeType != 1) {
      answers[i] = answers[i].previousSibling;
    }

    if (answers[i].getAttribute('customElement') == 'true') {
        answers[i] = answers[i].getElementsByTagName('table')[0];
    }

    setChecked(answers[i], false);
    answers[i].value = "";
    var colSumId = answers[i].colSumId;
    var rowSumId = answers[i].rwSumId;
    if (colSumId) {
        document.getElementById(colSumId).value = "";
    }
    if (rowSumId) {
        document.getElementById(rowSumId).value = "";
    }

    var optional = document.getElementById(answers[i].id + "_optional");
    if (optional != null) {
      optional.style.display = "none";
    }
  }
  var autoSumRows = document.getElementById(questionGuid + "rowsSum");
  var autoSumColumns = document.getElementById(questionGuid + "columnsSum");
  if (autoSumRows) {
      autoSumRows.value = "";
  }
  if (autoSumColumns) {
      autoSumColumns.value = "";
  }
}

function resetDontKnow(question) {
  var dontKnows = findChildNodesByType(question, "dontKnow");
  if (dontKnows.length > 0) {
    dontKnows[0] = dontKnows[0].previousSibling;
    while (dontKnows[0].nodeType != 1) {
      dontKnows[0] = dontKnows[0].previousSibling;
    }

    if (dontKnows[0].getAttribute('customElement') == 'true') {
        dontKnows[0] = dontKnows[0].getElementsByTagName('table')[0];
    }

    if (isChecked(dontKnows[0])) {
        setChecked(dontKnows[0], false);
    }

    clearOPSField(dontKnows[0]);
  }
}

function resetNoneOfThese(question) {
  var noneOfThese = findChildNodesByType(question, "noneOfThese");
  if (noneOfThese.length > 0) {
    noneOfThese[0] = noneOfThese[0].previousSibling;
    while (noneOfThese[0].nodeType != 1) {
      noneOfThese[0] = noneOfThese[0].previousSibling;
    }

    if (noneOfThese[0].getAttribute('customElement') == 'true') {
        noneOfThese[0] = noneOfThese[0].getElementsByTagName('table')[0];
    }

    if (isChecked(noneOfThese[0])) {
        setChecked(noneOfThese[0], false);
    }
    clearOPSField(noneOfThese[0]);
  }
}

function clearOPSField(startNode) {
    var optionals = findChildNodesByType(startNode.parentNode, "custom");
    if (optionals.length > 0) {
      var optional = optionals[0].previousSibling;
      while (optional.nodeType != 1) {
        optional = optional.previousSibling;
      }

      var controls = optional.parentNode.getElementsByTagName('INPUT');
      for (var i = 0; i < controls.length; i++) {
        controls[i].value="";
      }
    }
}

function subscribeCheckboxes(question) {
  function subscribeAnswer(answer, question) {
    var control = answer.previousSibling;

    while (control.nodeType != 1) {
      control = control.previousSibling;
    }

    if (control.getAttribute('customElement') == 'true') {
        control = control.getElementsByTagName('table')[0];
    }

    var id = control.id + "_optional";
    control.highNode = question;
    control.onclick = function() {
      var value = this.name;
      var inputs;
      if (value && value.length > 0) {
        inputs = findChildNodesByAttribute(this.highNode, value, "name");
      }
      else {
        inputs = new Array();
        inputs.push(this);
      }

      var visibility;
      var controlDiv;
      for (var i = 0; i < inputs.length; i++) {
        visibility = "none";
        if (isChecked(inputs[i])) {
          visibility = "inline";
        }
        controlDiv = document.getElementById(inputs[i].id + "_optional");
        if (controlDiv != null) {
          controlDiv.style.display = visibility;
        }
      }

      // process uncheckAll property (for checkboxes answers only)
      if (answer.getAttribute("answerType") == "checkboxes") {
          var answers = findChildNodesByType(question, "answer");
          var isUncheckAll = this.getAttribute("uncheckAll") == "true";
          for (var i = 0; i < answers.length; i++) {
              answers[i] = answers[i].previousSibling;
              while (answers[i].nodeType != 1) {
                  answers[i] = answers[i].previousSibling;
              }
              if (answers[i].getAttribute('customElement') == 'true') {
                  answers[i] = answers[i].getElementsByTagName('table')[0];
              }
              if (answers[i] != this && (isUncheckAll || answers[i].getAttribute("uncheckAll") == "true")) {
                  setChecked(answers[i], false)
                  answers[i].value = "";
                  var optional = document.getElementById(answers[i].id + "_optional");
                  if (optional != null) {
                      optional.style.display = "none";
                  }
              }
          }
      }

      resetDontKnow(this.highNode);
      resetNoneOfThese(this.highNode);
    }
    control = null;
  }

  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var answers = findChildNodesByType(question, "answer");
  for (var i = 0; i < answers.length; i++) {
    subscribeAnswer(answers[i], question);
  }
}

function subscribeRadiogroup(question) {
  subscribeCheckboxes(question);
}

function subscribeYesnoitem(question) {
  subscribeCheckboxes(question);
}

function subscribeNumeric(question) {
  function subscribeAnswer(answer, question) {
    answer = answer.previousSibling;

    while (answer.nodeType != 1) {
      answer = answer.previousSibling;
    }

    var id = answer.id + "_optional";
    answer.highNode = question;
    if (document.getElementById(id) != null) {
      answer.onkeyup = function() {
        var visibility = "none";
        if (this.value.length > 0) {
          visibility = "inline";
        }
        var element = document.getElementById(this.id + "_optional");
        element.style.display = visibility;

        resetDontKnow(this.highNode);
        resetNoneOfThese(this.highNode);
      }
      answer = null;
    }
    else {
      answer.onkeyup = function() {
        resetDontKnow(this.highNode);
        resetNoneOfThese(this.highNode);
      }
      answer = null;
    }
  }

  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var answers = findChildNodesByType(question, "answer");
  for (var i = 0; i < answers.length; i++) {
    subscribeAnswer(answers[i], question);
  }
}

function subscribeOpentext(question) {
  subscribeNumeric(question);
}

function subscribeTextarea(question) {
  subscribeNumeric(question);
}

function subscribeCombobox(question) {
  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var answers = findChildNodesByType(question, "answer");
  if (answers.length > 0) {
    answers[0] = answers[0].previousSibling;
    while (answers[0].nodeType != 1) {
      answers[0] = answers[0].previousSibling;
    }
    answers[0].highNode = question;
    answers[0].onchange = function() {
      resetDontKnow(this.highNode);
      resetNoneOfThese(this.highNode);
    }
    answers[0] = null;
  }
}

function subscribeRanking(question) {
  function subscribeAnswer(answer, highNode) {
    answer = answer.previousSibling;

    while (answer.nodeType != 1) {
      answer = answer.previousSibling;
    }

    answer.highNode = highNode;
    answer.onclick = function() {
      if (this.value.length > 0)
        return;

      var tmp = this;
      tmp.collectItems = function() {
        var items = findChildNodesByType(this.highNode, "answer");
        var item;
        var res = new Array();
        for (var i = 0; i < answers.length; i++) {
          item = answers[i].previousSibling;
          while (item.nodeType != 1) {
            item = item.previousSibling;
          }
          res.push(new Object());
          res[i].value = item.value;
          res[i].id = item.id;
        }
        return res;
      }
      tmp = null;

      var items = this.collectItems();
      var count = 0;
      for (var i = 0; i < items.length; i++) {
        if (items[i].value.length > 0 && !isNaN(items[i].value)) {
          count++;
        }
      }

      if (this.value.length > 0) {
        var item;
        for (var i = 0; i < items.length; i++) {
          item = document.getElementById(items[i].id);
          if (parseInt(item.value) > parseInt(this.value) && !isNaN(item.value)) {
            item.value = --item.value;
          }
        }
        this.value = "";
      }
      else {
        this.value = count + 1;
      }

      resetDontKnow(this.highNode);
      resetNoneOfThese(this.highNode);
    }
    answer = null;
  }

  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var answers = findChildNodesByType(question, "answer");
  for (var i = 0; i < answers.length; i++) {
    subscribeAnswer(answers[i], question);
  }
}

function subscribeMatrix(question) {
  var subType = question.getAttribute("subType");
  var questionGuid = '' + question.id;
  if (subType == "singlePerLineAndColumn") {
    return subscribeSinglePerColumn(question.previousSibling);
  }
  else if (subType == "single" || subType == "singlePerLine" || subType == "several") {
    return subscribeBooleanMatrix(question.previousSibling);
  }
  else if (subType == "numeric") {
    return subscribeNumericMatrix(question.previousSibling);
  }
  else if (subType == "numericSum") {
    return subscribeNumericSum(question.previousSibling, questionGuid);
  }
  else if (subType == "numericSumForLines") {
    return subscribeNumericSumForLines(question.previousSibling, questionGuid);
  }
  else if (subType == "numericSumForColumns") {
    return subscribeNumericSumForColumns(question.previousSibling, questionGuid);
  }
  else if (subType == "combobox") {
    return subscribeComboboxMatrix(question.previousSibling);
  }
}

function subscribeSinglePerColumn(question) {
  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var controls = findChildNodesByType(question, "answer");
  for (var i = 0; i < controls.length; i++) {
    controls[i] = controls[i].previousSibling;
    while (controls[i].nodeType != 1) {
      controls[i] = controls[i].previousSibling;
    }

    if (controls[i].getAttribute('customElement') == 'true') {
        controls[i] = controls[i].getElementsByTagName('table')[0];
    }

    controls[i].highNode = question;
    controls[i].onclick = function() {
      var colId = this.getAttribute("columnId");
      var highNode = this.getAttribute("highNode");
      var inputs = findChildNodesByAttribute(this.highNode, colId, "columnId");
      for (var j = 0; j < inputs.length; j++) {
        if (inputs[j] != this) {
          setChecked(inputs[j], false);
        }
      }

      resetDontKnow(this.highNode);
      resetNoneOfThese(this.highNode);
    }
    controls[i] = null;
  }
}

function subscribeBooleanMatrix(question) {
  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var controls = findChildNodesByType(question, "answer");
  for (var i = 0; i < controls.length; i++) {
    controls[i] = controls[i].previousSibling;
    while (controls[i].nodeType != 1) {
      controls[i] = controls[i].previousSibling;
    }

    controls[i].highNode = question;
    controls[i].onclick = function() {
      resetDontKnow(this.highNode);
      resetNoneOfThese(this.highNode);
    }
    controls[i] = null;
  }
}

function subscribeNumericMatrix(question) {
  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var controls = findChildNodesByType(question, "answer");
  for (var i = 0; i < controls.length; i++) {
    controls[i] = controls[i].previousSibling;
    while (controls[i].nodeType != 1) {
      controls[i] = controls[i].previousSibling;
    }

    controls[i].highNode = question;
    controls[i].onkeyup = function() {
      resetDontKnow(this.highNode);
      resetNoneOfThese(this.highNode);
    }
    controls[i] = null;
  }
}

function trimAll(sString){
    pos = 0;
    while (sString.substring(pos, pos + 1) == ' ' || sString.substring(pos, pos + 1) == '\r' || sString.substring(pos, pos + 1) == '\n') pos++;
    sString = sString.substring(pos, sString.length);
    pos = sString.length;
    while (sString.substring(pos - 1, pos) == ' ' || sString.substring(pos - 1, pos) == '\r' || sString.substring(pos - 1, pos) == '\n') pos--;
    sString = sString.substring(0, pos);
    return sString;
}

function subscribeNumericSum(question, questionGuid) {
  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var controls = findChildNodesByType(question, "answer");
  var colSumId;
  var rowSumId;
  for (var i = 0; i < controls.length; i++) {
    colSumId = controls[i].getAttribute("columnSumId");
    rowSumId = controls[i].getAttribute("rowSumId");
    controls[i] = controls[i].previousSibling;
    while (controls[i].nodeType != 1) {
      controls[i] = controls[i].previousSibling;
    }

    controls[i].highNode = question;
    controls[i].colSumId = colSumId;
    controls[i].rwSumId = rowSumId;
    controls[i].onkeyup = function() {
      var sumId = this.colSumId;
      var inputs = findChildNodesByAttribute(this.highNode, sumId, "columnSumId");
      var sum = 0;
      var str;
      for (var j = 0; j < inputs.length; j++) {
        inputs[j] = inputs[j].previousSibling;
        while (inputs[j].nodeType != 1) {
          inputs[j] = inputs[j].previousSibling;
        }

        str = trimAll(new String(inputs[j].value));
        if (!isNaN(str) && str.length > 0 && str.indexOf('0X') == -1 && str.indexOf('0x') == -1) {
          sum += parseInt(str, 10);
        }
      }
      var element = document.getElementById(sumId);
      element.value = sum;

      sumId = this.rwSumId;
      inputs = findChildNodesByAttribute(this.highNode, sumId, "rowSumId");
      sum = 0;
      for (var j = 0; j < inputs.length; j++) {
        inputs[j] = inputs[j].previousSibling;
        while (inputs[j].nodeType != 1) {
          inputs[j] = inputs[j].previousSibling;
        }

        str = trimAll(new String(inputs[j].value));
        if (!isNaN(str) && str.length > 0 && str.indexOf('0X') == -1 && str.indexOf('0x') == -1) {
          sum += parseInt(str, 10);
        }
      }
      var nextElement = document.getElementById(sumId);
      nextElement.value = sum;

      var columnsSum = document.getElementById(questionGuid + "columnsSum");
      var rowsSum = document.getElementById(questionGuid + "rowsSum");
      var totalSum = calculateTotalSum(question);
      columnsSum.value = totalSum;
      rowsSum.value = totalSum;

      resetDontKnow(this.highNode);
      resetNoneOfThese(this.highNode);
    }
    controls[i] = null;
  }
}

function subscribeNumericSumForLines(question, questionGuid) {
  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var controls = findChildNodesByType(question, "answer");
  var rowSumId;
  for (var i = 0; i < controls.length; i++) {
    rowSumId = controls[i].getAttribute("rowSumId");
    controls[i] = controls[i].previousSibling;
    while (controls[i].nodeType != 1) {
      controls[i] = controls[i].previousSibling;
    }

    controls[i].highNode = question;
    controls[i].rwSumId = rowSumId;
    controls[i].onkeyup = function() {

      var sumId = this.rwSumId;
      var inputs = findChildNodesByAttribute(this.highNode, sumId, "rowSumId");
      var sum = 0;
      var str;
      for (var j = 0; j < inputs.length; j++) {
        inputs[j] = inputs[j].previousSibling;
        while (inputs[j].nodeType != 1) {
          inputs[j] = inputs[j].previousSibling;
        }

        str = trimAll(new String(inputs[j].value));
        if (!isNaN(str) && str.length > 0 && str.indexOf('0X') == -1 && str.indexOf('0x') == -1) {
          sum += parseInt(str, 10);
        }
      }
      var nextElement = document.getElementById(sumId);
      nextElement.value = sum;

      var rowsSum = document.getElementById(questionGuid + "rowsSum");
      rowsSum.value = calculateTotalSum(question);

      resetDontKnow(this.highNode);
      resetNoneOfThese(this.highNode);
    }
    controls[i] = null;
  }
}

function subscribeNumericSumForColumns(question, questionGuid) {
  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var controls = findChildNodesByType(question, "answer");
  var colSumId;
  for (var i = 0; i < controls.length; i++) {
    colSumId = controls[i].getAttribute("columnSumId");
    controls[i] = controls[i].previousSibling;
    while (controls[i].nodeType != 1) {
      controls[i] = controls[i].previousSibling;
    }

    controls[i].highNode = question;
    controls[i].colSumId = colSumId;
    controls[i].onkeyup = function() {
      var sumId = this.colSumId;
      var inputs = findChildNodesByAttribute(this.highNode, sumId, "columnSumId");
      var sum = 0;
      var str;
      for (var j = 0; j < inputs.length; j++) {
        inputs[j] = inputs[j].previousSibling;
        while (inputs[j].nodeType != 1) {
          inputs[j] = inputs[j].previousSibling;
        }

        str = trimAll(new String(inputs[j].value));
        if (!isNaN(str) && str.length > 0 && str.indexOf('0X') == -1 && str.indexOf('0x') == -1) {
          sum += parseInt(str, 10);
        }
      }
      var element = document.getElementById(sumId);
      element.value = sum;

      var columnsSum = document.getElementById(questionGuid + "columnsSum");
      columnsSum.value = calculateTotalSum(question);

      resetDontKnow(this.highNode);
      resetNoneOfThese(this.highNode);
    }
    controls[i] = null;
  }
}

function calculateTotalSum(question) {
    var cells = findChildNodesByType(question, "answer");
    var totalSum = 0;
    var value;
    for (var i = 0; i < cells.length; i++) {
      cells[i] = cells[i].previousSibling;
      value = trimAll(new String(cells[i].value));
      if (!isNaN(value) && value.length > 0 && value.indexOf('0X') == -1 && value.indexOf('0x') == -1) {
        totalSum += parseInt(value, 10);
      }
    }
    return totalSum;
}

function subscribeComboboxMatrix(question) {
  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var columnPrefixes = new Array();
  var maxWidthForEachColumn = new Array();
  var allColumnPrefixes = new Array();
  var prefix;
  var columnPrefix;
  var index;
    
  var controls = findChildNodesByType(question, "answer");
  for (var i = 0; i < controls.length; i++) {

    if (ie) {
        //fix of issue AS-1674
        prefix = controls[i].getAttribute("answerPrefix");
        columnPrefix = prefix.substring(0, prefix.indexOf(','));
        allColumnPrefixes.push(columnPrefix);
        index = columnPrefixes.indexOf(columnPrefix);
        if (index == -1) {
            columnPrefixes.push(columnPrefix);                           // see AnswerVO.DEFAULT_COLUMN_WIDTH
            maxWidthForEachColumn.push(Math.max(controls[i].offsetWidth, 200));
            index = columnPrefixes.length - 1;
        }
    }

    controls[i] = controls[i].previousSibling;
    while (controls[i].nodeType != 1) {
      controls[i] = controls[i].previousSibling;
    }

    if (ie) {
        controls[i].style.width = '';
        var newWidth = controls[i].offsetWidth;

        if (newWidth > maxWidthForEachColumn[index]) {
            maxWidthForEachColumn[index] = newWidth;
        }
    }

    controls[i].highNode = question;
    controls[i].onchange = function() {
      resetDontKnow(this.highNode);
      resetNoneOfThese(this.highNode);
    }
  }
  for (var i = 0; i < controls.length; i++) {
    if (ie) {
        columnPrefix = allColumnPrefixes[i];
        if (columnPrefix) {
            index = columnPrefixes.indexOf(columnPrefix);
            if (index != -1) {
                controls[i].style.width = maxWidthForEachColumn[index];
            }
        }
    }
    controls[i] = null;
  }
}

function subscribeCustoms() {
  var questions = findChildNodesByType(document.body, "question");
  for (var i = 0; i < questions.length; i++) {
    subscribeQuestionCustoms(questions[i]);
  }
}

function addCustom(node) {
  var controls = node.getElementsByTagName('INPUT');
  var newBR = document.createElement('BR');
  node.appendChild(newBR);
  var newInput = document.createElement('INPUT');
  node.appendChild(newInput);
  newInput.customIdx = controls.length - 1;
  newInput.onkeyup = customOnkeyup;
  newInput.id = node.id + "_" + newInput.customIdx;
}

function deleteCustom(node, custom) {
  var controls = node.getElementsByTagName('INPUT');
  var customLength = controls.length;
  if (customLength < 2)
    return;

  for (var i = custom.customIdx; i < customLength - 1; i++) {
    controls[i].value = controls[i + 1].value;
    controls[i].oldValue = controls[i + 1].oldValue;
  }

  node.removeChild(controls[customLength - 1]);
  controls = node.getElementsByTagName('BR');
  node.removeChild(controls[controls.length - 1]);
}

function customOnkeyup() {
      if (this.oldValue == null)
        this.oldValue = '';

      if (this.oldValue == this.value) {
        return;
      }

      if (this.value.length > 0) {
        if (this.oldValue.length == 0)
          addCustom(this.parentNode);
      }
      else {
        deleteCustom(this.parentNode, this);
      }
      this.oldValue = this.value;
}

function subscribeQuestionCustoms(question) {
  question = question.previousSibling;

  while (question.nodeType != 1) {
    question = question.previousSibling;
  }

  var controls = findChildNodesByType(question, "custom");

  for (var i = 0; i < controls.length; i++) {
    controls[i] = controls[i].previousSibling;
    while (controls[i].nodeType != 1) {
      controls[i] = controls[i].previousSibling;
    }

    controls[i].customIdx = 0;
    controls[i].onkeyup = customOnkeyup;
  }
}

function collectQuestionsFlash(str, questionId) {
    document.getElementById('answerField' + questionId).value = str;
}
