﻿Type.registerNamespace("NoviSurvey");

// ----------- color picker -----------

NoviSurvey.ColorPicker = function(swatchId, colorCodeId, targetId) {
  this._swatch = $get(swatchId);
  var swatchClickDel = Function.createDelegate(this, this.clickSwatch);
  $addHandler(this._swatch, "click", swatchClickDel);

  this._colorCode = $get(colorCodeId);
  var colorCodeChangedDel = Function.createDelegate(this, this.colorCodeChanged);
  $addHandler(this._colorCode, "blur", colorCodeChangedDel);

  if (targetId) {
    this._target = $get(targetId);
  }

  this.createDiv();

  this._documentClickDel = Function.createDelegate(this, this.clickDocument);
}

NoviSurvey.ColorPicker.prototype = {

  createDiv: function() {
    this._colorPickerDiv = $get('colorPickerDiv');

    if (this._colorPickerDiv.childNodes.length > 1) {
      return;
    }

    // initializes colors and behavior of the popup
    var colors = new Array(
                "#000000", "#000033", "#000066", "#000099", "#0000CC", "#0000FF", "#006600", "#006633", "#006666", "#006699", "#0066CC", "#0066FF", "#00CC00", "#00CC33", "#00CC66", "#00CC99", "#00CCCC", "#00CCFF",
                "#003300", "#003333", "#003366", "#003399", "#0033CC", "#0033FF", "#009900", "#009933", "#009966", "#009999", "#0099CC", "#0099FF", "#00FF00", "#00FF33", "#00FF66", "#00FF99", "#00FFCC", "#00FFFF",
                "#330000", "#330033", "#330066", "#330099", "#3300CC", "#3300FF", "#336600", "#336633", "#336666", "#336699", "#3366CC", "#3366FF", "#33CC00", "#33CC33", "#33CC66", "#33CC99", "#33CCCC", "#33CCFF",
                "#333300", "#333333", "#333366", "#333399", "#3333CC", "#3333FF", "#339900", "#339933", "#339966", "#339999", "#3399CC", "#3399FF", "#33FF00", "#33FF33", "#33FF66", "#33FF99", "#33FFCC", "#33FFFF",
                "#660000", "#660033", "#660066", "#660099", "#6600CC", "#6600FF", "#666600", "#666633", "#666666", "#666699", "#6666CC", "#6666FF", "#66CC00", "#66CC33", "#66CC66", "#66CC99", "#66CCCC", "#66CCFF",
                "#663300", "#663333", "#663366", "#663399", "#6633CC", "#6633FF", "#669900", "#669933", "#669966", "#669999", "#6699CC", "#6699FF", "#66FF00", "#66FF33", "#66FF66", "#66FF99", "#66FFCC", "#66FFFF",
                "#990000", "#990033", "#990066", "#990099", "#9900CC", "#9900FF", "#996600", "#996633", "#996666", "#996699", "#9966CC", "#9966FF", "#99CC00", "#99CC33", "#99CC66", "#99CC99", "#99CCCC", "#99CCFF",
                "#993300", "#993333", "#993366", "#993399", "#9933CC", "#9933FF", "#999900", "#999933", "#999966", "#999999", "#9999CC", "#9999FF", "#99FF00", "#99FF33", "#99FF66", "#99FF99", "#99FFCC", "#99FFFF",
                "#CC0000", "#CC0033", "#CC0066", "#CC0099", "#CC00CC", "#CC00FF", "#CC6600", "#CC6633", "#CC6666", "#CC6699", "#CC66CC", "#CC66FF", "#CCCC00", "#CCCC33", "#CCCC66", "#CCCC99", "#CCCCCC", "#CCCCFF",
                "#CC3300", "#CC3333", "#CC3366", "#CC3399", "#CC33CC", "#CC33FF", "#CC9900", "#CC9933", "#CC9966", "#CC9999", "#CC99CC", "#CC99FF", "#CCFF00", "#CCFF33", "#CCFF66", "#CCFF99", "#CCFFCC", "#CCFFFF",
                "#FF0000", "#FF0033", "#FF0066", "#FF0099", "#FF00CC", "#FF00FF", "#FF6600", "#FF6633", "#FF6666", "#FF6699", "#FF66CC", "#FF66FF", "#FFCC00", "#FFCC33", "#FFCC66", "#FFCC99", "#FFCCCC", "#FFCCFF",
                "#FF3300", "#FF3333", "#FF3366", "#FF3399", "#FF33CC", "#FF33FF", "#FF9900", "#FF9933", "#FF9966", "#FF9999", "#FF99CC", "#FF99FF", "#FFFF00", "#FFFF33", "#FFFF66", "#FFFF99", "#FFFFCC", "#FFFFFF",
                "#000000", "#1C1C1C", "#2A2A2A", "#383838", "#464646", "#545454", "#626262", "#707070", "#7E7E7E", "#8C8C8C", "#9A9A9A", "#A8A8A8", "#B6B6B6", "#C4C4C4", "#D2D2D2", "#E0E0E0", "#EEEEEE", "#FCFCFC");

    var borderColor = '#333333';

    var cpTable = document.createElement('table');
    cpTable.style.borderCollapse = 'collapse';
    cpTable.style.background = borderColor;
    this._colorPickerDiv.appendChild(cpTable);

    var cpTableBody = document.createElement('tbody');
    cpTable.appendChild(cpTableBody);

    var cpTableCurRow;
    var rowCellCount = 18;
    var cellHeight = 14;
    var cellWidth = 12;
    NoviSurvey.ColorPicker.prototype.colorCells = new Array();

    var q = NoviSurvey.ColorPicker.prototype.colorCells;

    for (var i = 0; i < colors.length; i++) {

      if (i % rowCellCount == 0) {
        cpTableCurRow = document.createElement("tr");
        cpTableBody.appendChild(cpTableCurRow);
      }

      var currentCell = document.createElement("td");
      NoviSurvey.ColorPicker.prototype.colorCells[i] = currentCell;
      currentCell.style.backgroundColor = colors[i];
      currentCell.style.width = cellWidth + "px";
      currentCell.style.height = cellHeight + "px";
      currentCell.style.padding = "0px";
      currentCell.style.border = "1px";
      currentCell.style.borderColor = borderColor;
      currentCell.style.borderStyle = "solid";
      cpTableCurRow.appendChild(currentCell);

      var mouseOverColorDel = Function.createDelegate(this, this.mouseOverColor);
      $addHandler(currentCell, "mouseover", mouseOverColorDel);
    }

    // layout for current color
    var curColorTable = document.createElement("table");
    curColorTable.style.borderCollapse = 'collapse';
    curColorTable.style.borderWidth = '0px 1px 1px 1px';
    curColorTable.style.borderColor = borderColor;
    curColorTable.style.borderStyle = 'solid';
    curColorTable.style.background = '#FFFFFF';
    this._colorPickerDiv.appendChild(curColorTable);

    var colorTableBody = document.createElement("tbody");
    curColorTable.appendChild(colorTableBody);

    var colorTableRow = document.createElement("tr");
    colorTableBody.appendChild(colorTableRow);

    this._selectedColorCell = document.createElement("td");
    this._selectedColorCell.style.background = '#FFFFFF';
    this._selectedColorCell.style.padding = '0px';
    this._selectedColorCell.style.height = '20px';
    this._selectedColorCell.style.width = (cellWidth * Math.floor(rowCellCount / 2)) + "px"
    colorTableRow.appendChild(this._selectedColorCell);

    this._selectedColorValueCell = document.createElement("td");
    this._selectedColorValueCell.style.background = '#FFFFFF';
    this._selectedColorCell.style.padding = '0px';
    this._selectedColorValueCell.style.textAlign = 'center';
    this._selectedColorValueCell.style.height = '20px';
    this._selectedColorValueCell.style.width = (cellWidth * (rowCellCount - Math.floor(rowCellCount / 2)) - 4 + rowCellCount + 1) + "px";

    colorTableRow.appendChild(this._selectedColorValueCell);
  },

  setCellsClickAction: function() {
    var i;
    for (i = 0; i < NoviSurvey.ColorPicker.prototype.colorCells.length; i++) {
      if (NoviSurvey.ColorPicker.prototype.mouseClickDel) {
        $removeHandler(NoviSurvey.ColorPicker.prototype.colorCells[i], "click", NoviSurvey.ColorPicker.prototype.mouseClickDel);
      }
    }

    NoviSurvey.ColorPicker.prototype.mouseClickDel = Function.createDelegate(this, this.clickColor);

    for (i = 0; i < NoviSurvey.ColorPicker.prototype.colorCells.length; i++) {
      $addHandler(NoviSurvey.ColorPicker.prototype.colorCells[i], "click", NoviSurvey.ColorPicker.prototype.mouseClickDel);
    }
  },

  mouseOverColor: function(evt) {
    evt.stopPropagation();
    this._selectedColorCell.style.backgroundColor = evt.target.style.backgroundColor;
    this._selectedColorValueCell.innerHTML = this.convertColor(evt.target.style.backgroundColor);
  },

  clickColor: function(evt) {
    evt.stopPropagation();
    var color = this.convertColor(evt.target.style.backgroundColor);
    this.setColorSwatch(color);
    this._colorCode.value = color;
    this._colorPickerDiv.style.visibility = 'hidden';
    this._colorPickerDiv.style.display = 'none';

    $removeHandler(document, 'click', this._documentClickDel);
  },

  clickSwatch: function(evt) {
    evt.stopPropagation();
    var swatchPos = findItemPos(this._swatch);
    this._colorPickerDiv.style.visibility = 'visible';
    this._colorPickerDiv.style.display = 'inline';
    this._colorPickerDiv.style.left = swatchPos[0] + 'px';
    this._colorPickerDiv.style.top = (swatchPos[1] + this._swatch.offsetHeight + 2) + 'px';

    this.setCellsClickAction();

    $addHandler(document, 'click', this._documentClickDel);
  },

  clickDocument: function(evt) {
    evt.stopPropagation();
    this._colorPickerDiv.style.visibility = 'hidden';
    this._colorPickerDiv.style.display = 'none';

    $removeHandler(document, 'click', this._documentClickDel);
  },

  colorCodeChanged: function(evt) {
    evt.stopPropagation();
    this.setColorSwatch(this._colorCode.value);
  },

  setColorSwatch: function(color) {
    // color code in the form #RGB where R, G, B are hex integers in the range of 0-FF  
    var swatchColor = color.match(/^#([0-9A-F]){6}$/i) ? color : '#FFFFFF';

    if (this._swatch.style.backgroundColor != swatchColor) {
      this._swatch.style.backgroundColor = swatchColor;
    }

    if (this._target) {
      this._target.style.color = color;
    }
  },

  // converts rgb(r, g, b) to #rgb
  convertColor: function(color) {
    color = color.toUpperCase().replace(/\s+/g, "");
    var res;
    if (color.indexOf('#') >= 0) {
      res = color;
    } else {
      var channels = color.replace(/RGB\(/, "").replace(/\)/, "").split(',');

      var redChannel = parseInt(channels[0]).toString(16);
      redChannel = "00".substring(0, 2 - redChannel.length) + redChannel;

      var greenChannel = parseInt(channels[1]).toString(16);
      greenChannel = "00".substring(0, 2 - greenChannel.length) + greenChannel;

      var blueChannel = parseInt(channels[2]).toString(16);
      blueChannel = "00".substring(0, 2 - blueChannel.length) + blueChannel;

      res = '#' + (redChannel + greenChannel + blueChannel).toUpperCase();
    }

    return res;
  }
}

NoviSurvey.ColorPicker.registerClass('NoviSurvey.ColorPicker', null, Sys.IDisposable);

// ----------- documentation -----------

NoviSurvey.Documentation = function(docLink, baseUrl, helpKey, tabHelpKey, culture) {
  this._docLink = $get(docLink);
  this._baseUrl = baseUrl;
  this._helpKey = helpKey;
  this._tabHelpKey = tabHelpKey;
  this._culture = culture;
}

NoviSurvey.Documentation.prototype = {
  setTabHelpKey: function(tabHelpKey) {
    this._tabHelpKey = tabHelpKey;
  },

  showDocumentation: function() {
    var page = "index.html" + (("" + this._helpKey).length > 0 ? "?" + this._helpKey : "");
    page += ("" + this._tabHelpKey).length > 0 && page !== "index.html" ? "-" + this._tabHelpKey : "";
    this._docLink.href = this._baseUrl + 'Help/' + this._culture + "/" + page;

    popupWindow(this._docLink.href, 1000, 700, null);
  }
}

NoviSurvey.Documentation.registerClass('NoviSurvey.Documentation', null, Sys.IDisposable);

// ----------- optional radio buttons & managed single selection checkbox group -----------

NoviSurvey.OptionalCheckedItems = function(groupName) {
  this._currentlyChecked = null;
  this._radioButtons = new Array();

  if (groupName) {
    var buttons = findChildrenButtons($get(groupName));
    for (var i = 0; i < buttons.length; i++) {
      this.addButton(buttons[i]);
    }
  }
}

NoviSurvey.OptionalCheckedItems.prototype = {

  clickButton: function(evt) {
    var radioButton = evt.target;
    for (var i = 0; i < this._radioButtons.length; i++) {
      if (this._radioButtons[i] !== radioButton) {
        this._radioButtons[i].checked = false;
      }
    }
    if (radioButton === this._currentlyChecked) {
      radioButton.checked = false;
      this._currentlyChecked = null;
    } else {
      this._currentlyChecked = radioButton;
    }
  },

  addButton: function(radioButton) {
    if (radioButton === null) {
      return;
    }
    var clickButtonDel = Function.createDelegate(this, this.clickButton);
    $addHandler(radioButton, "click", clickButtonDel);
    this._radioButtons[this._radioButtons.length] = radioButton;
    if (radioButton.checked === true) {
      this._currentlyChecked = radioButton;
    }
  }
}

NoviSurvey.OptionalCheckedItems.registerClass('NoviSurvey.OptionalCheckedItems', null, Sys.IDisposable);

// ----------- show/hide 'other' option textbox based on options selected -----------

NoviSurvey.OtherFreeTextAnswer = function(controlId, otherPanelId) {

  // the 'other' option is either an input (checkbox or radio button) or an option in a select
  var ctl = $get(controlId);
  if (ctl === null) {
    return;
  }

  if (ctl.tagName.toUpperCase() === "INPUT") {
    var optionsControl = firstParent(ctl, "TABLE");
    var buttons = findChildrenButtons(optionsControl);
    var clickOptionDel = Function.createDelegate(this, this.clickOption);
    if (buttons.length > 0) {
      for (var i = 0; i < buttons.length; i++) {
        $addHandler(buttons[i], "click", clickOptionDel);
      }
      this._otherOption = ctl;
    }
  } else if (ctl.length > 0) {
    var select = ctl[0].parentNode;

    var changeOptionDel = Function.createDelegate(this, this.changeOption);
    $addHandler(select, "change", changeOptionDel);
    this._otherOption = ctl[ctl.length - 1];
  }

  this._otherPanel = $get(otherPanelId);
}

NoviSurvey.OtherFreeTextAnswer.prototype = {

  clickOption: function(evt) {
    this._otherPanel.style["display"] = this._otherOption.checked? "block" : "none";
    this._otherPanel.style["visibility"] = this._otherOption.checked ? "visible" : "hidden";
  },

  changeOption: function(evt) {
    var select = evt.target;
    var otherOptionSelected = select.selectedIndex == select.length - 1;
    this._otherPanel.style["display"] = otherOptionSelected ? "block" : "none";
    this._otherPanel.style["visibility"] = otherOptionSelected ? "visible" : "hidden";
  }
}

NoviSurvey.OtherFreeTextAnswer.registerClass('NoviSurvey.OtherFreeTextAnswer', null, Sys.IDisposable);

// ----------- highlight radio buttons and checkboxes embedded in a table cell when selected -----------

NoviSurvey.HighlightableItems = function() {
  this._items = new Array();
  this._itemCells = new Array();
}

NoviSurvey.HighlightableItems.prototype = {
  clickItem: function(evt) {
    var item = evt.target;

    for (var i = 0; i < this._items.length; i++) {
      if (this._items[i] === item) {
        this._itemCells[i].className = this._itemCells[i].className !== "selected" ? "selected" : "";
      } else {
        if (item.type.toUpperCase() === 'RADIO') {
          this._itemCells[i].className = "";
        }
      }
    }
  },

  addItem: function(itemId) {
    var clickDel = Function.createDelegate(this, this.clickItem);
    var item = $get(itemId);
    if (item === null) {
      return;
    }
    $addHandler(item, "click", clickDel);

    this._items[this._items.length] = item;
    var itemCell = firstParent(item, "TD");
    this._itemCells[this._itemCells.length] = itemCell;
  }
}

NoviSurvey.HighlightableItems.registerClass('NoviSurvey.HighlightableItems', null, Sys.IDisposable);

// ----------- selectable table -----------

NoviSurvey.Table = function(selectedRowFieldID, tableId) {
  this._table = $get(tableId);

  if (!this._table) {
    return;
  }

  this._defaultStyle = "gridTableDefault";
  this._highlightedStyle = "gridTableHighlighted";
  this._selectedStyle = "gridTableSelected";

  // track the selection box for each row

  // selection in the table is tracked through a hidden field
  this._selected = $get(selectedRowFieldID);
  this._currentlySelectedRow = null;

  // add handlers on rows other than the header
  var clickRowDel = Function.createDelegate(this, this.clickRow);
  for (var i = 0; i < this._table.rows.length; i++) {
    var curRow = this._table.rows[i];
    if (curRow.childNodes.length > 1 && curRow.childNodes[1].tagName.toUpperCase() !== "TH") {
      $addHandler(curRow, "click", clickRowDel);
    }

    // set initial selection state   
    if (this._selected.value === curRow.getAttribute("hc")) {
      curRow.className = this._selectedStyle;
      this._currentlySelectedRow = curRow;
      firstChild(firstChild(curRow, "TD"), "INPUT").checked = true;
    }
  }
}

NoviSurvey.Table.prototype = {

  firstParentRow: function(x) {
    return firstParent(x, 'TR');
  },

  isFirstColumn: function(x) {
    var cell = firstParent(x, 'TD');
    return !cell.previousSibling || !cell.previousSibling.tagName || cell.previousSibling.tagName.toUpperCase() !== 'TD';
  },

  clickRow: function(evt) {
    var row = this.firstParentRow(evt.target);
    if (row.getAttribute("hc") === this._selected.value) {
      this._selected.value = "";
      this._currentlySelectedRow = null;
      row.className = this._highlightedStyle;
      firstChild(firstChild(row, "TD"), "INPUT").checked = false;
    } else {
      if (this._selected.value !== "" && this._currentlySelectedRow !== null) {
        this._currentlySelectedRow.className = this._defaultStyle;
        firstChild(firstChild(this._currentlySelectedRow, "TD"), "INPUT").checked = false;
      }
      row.className = this._selectedStyle;
      firstChild(firstChild(row, "TD"), "INPUT").checked = true;
      this._selected.value = row.getAttribute("hc");
      this._currentlySelectedRow = row;
    }

    // postback; no validation
    Sys.WebForms.PageRequestManager.getInstance()._doPostBack(this._table.id, '');
  }

}

NoviSurvey.Table.registerClass('NoviSurvey.Table', null, Sys.IDisposable);

// ----------- ranking shapes -----------

// note: rank is 1-based; indexing of shapes is 0-based

NoviSurvey.RankingShapes = function(tableId, currentRankHdnId, allowHalfSelection) {
  var table = $get("" + tableId);
  this._currentRankHdn = $get("" + currentRankHdnId);
  this._allowHalfSelection = Boolean(allowHalfSelection);

  var mouseOutTableDel = Function.createDelegate(this, this.mouseOutTable);
  $addHandler(table, "mouseout", mouseOutTableDel);

  var mouseOverShapeDel = Function.createDelegate(this, this.mouseOverShape);
  var mouseOutShapeDel = Function.createDelegate(this, this.mouseOutShape);
  var clickShapeDel = Function.createDelegate(this, this.clickShape);

  this._shapes = new Array();
  var row = table.rows[0];
  for (var i = 0; i < row.childNodes.length; i++) {
    var node = row.childNodes[i];
    if (node.tagName && node.tagName.toUpperCase() == 'TD') {
      for (var j = 0; j < node.childNodes.length; j++) {
        var innerNode = node.childNodes[j];
        if (innerNode.tagName && innerNode.tagName.toUpperCase() == 'IMG') {
          $addHandlers(innerNode, { "mouseover": mouseOverShapeDel, "mouseout": mouseOutShapeDel, "click": clickShapeDel });
          this._shapes[this._shapes.length] = innerNode;
        }
      }
    }
  }

  // note: see keys for images defined in AppKeys

  this._rightShapeToken = '_RIGHT';
  this._leftShapeToken = '_LEFT';

  this._notSelectedLeftHref = this._shapes[0].src.indexOf('_NOT_SELECTED_') == -1
    ? this._shapes[0].src.replace(/_SELECTED_/, '_NOT_SELECTED_')
    : this._shapes[0].src;

  this._selectedLeftHref = this._notSelectedLeftHref.replace(/_NOT_SELECTED_/, '_SELECTED_');

  this._notSelectedRightHref = this._shapes[1].src.indexOf('_NOT_SELECTED_') == -1
    ? this._shapes[1].src.replace(/_SELECTED_/, '_NOT_SELECTED_')
    : this._shapes[1].src;

  this._selectedRightHref = this._notSelectedRightHref.replace(/_NOT_SELECTED_/, '_SELECTED_');
}

NoviSurvey.RankingShapes.prototype = {

  mouseOutTable: function(evt) {
    this._firstEntry = true;
  },

  mouseOverShape: function(evt) {
    var shape = evt.target;

    var shapeIdx = this.shapeIdx(shape);
    var shapeRank = this.rankFromShapeIdx(shapeIdx);
    var curSelectedRank = this.selectedRank();

    for (var i = 0; i < this._shapes.length; i++) {
      var curRank = this.rankFromShapeIdx(i);
      if (curRank <= curSelectedRank) {
        continue;
      }

      var curShape = this._shapes[i];
      if (i < shapeIdx) {
        this.showSelected(curShape);
      } else if (i == shapeIdx) {
        // upon reentry in the table on a selected shape, keep the shape selected      
        if (this.isSelected(shape) && !this._firstEntry) {
          this.showNotSelected(shape);
        } else {
          this.showSelected(shape);
        }
      } else {
        this.showNotSelected(this._shapes[i]);
      }
    }

    this._firstEntry = false;
  },

  isSelected: function(shape) {
    return shape.src.indexOf(this._notSelectedToken) == -1;
  },

  showSelected: function(shape) {
    shape.src = shape.src.indexOf(this._leftShapeToken) != -1 ? this._selectedLeftHref : this._selectedRightHref;
  },

  showNotSelected: function(shape) {
    shape.src = shape.src.indexOf(this._leftShapeToken) != -1 ? this._notSelectedLeftHref : this._notSelectedRightHref;
  },

  mouseOutShape: function(evt) {
    var shape = evt.target;
    var selectedShapeIdx = this.shapeIdxFromRank(this.selectedRank());

    for (var i = 0; i < this._shapes.length; i++) {
      if (i > selectedShapeIdx) {
        this.showNotSelected(this._shapes[i]);
      } else {
        this.showSelected(this._shapes[i]);
      }
    }
  },

  clickShape: function(evt) {
    var shape = evt.target;
    var rankForSelected = this.rankFromShapeIdx(this.shapeIdx(shape));
    // either record selected value or deselected in the previously selected rank was selected
    this._currentRankHdn.value = this._currentRankHdn.value != rankForSelected ? rankForSelected : "0";
    this.mouseOverShape(evt);
  },

  selectedRank: function() {
    return this._currentRankHdn.value !== "" ? parseFloat(this._currentRankHdn.value) : 0;
  },

  shapeIdxFromRank: function(rank) {
    return 2 * rank - 1;
  },

  rankFromShapeIdx: function(shapeIdx) {
    return (this._allowHalfSelection ? 0.5 : 1) + (this._allowHalfSelection ? shapeIdx / 2.0 : Math.floor(shapeIdx / 2));
  },

  shapeIdx: function(shape) {
    var shapeIdx = 0;
    for (; shapeIdx < this._shapes.length; shapeIdx++) {
      if (this._shapes[shapeIdx] == shape) {
        break;
      }
    }
    return shapeIdx;
  }
}

NoviSurvey.RankingShapes.registerClass('NoviSurvey.RankingShapes', null, Sys.IDisposable);

// ----------- Ping -----------

NoviSurvey.Ping = function(sessionId, timeout, errorPage) {
  NoviSurvey.Ping.prototype.sessionId = sessionId;
  NoviSurvey.Ping.prototype.timeout = timeout;
  NoviSurvey.Ping.prototype.errorPage = errorPage;
  this.doPing();
}

NoviSurvey.Ping.prototype = {
  doPing: function() {
    NoviSurvey.Web.WebServices.ClientUtilsWebService.Ping(NoviSurvey.Ping.prototype.pingSucess, OnFailedDoNothing);
    setTimeout('NoviSurvey.Ping.prototype.doPing();', NoviSurvey.Ping.prototype.timeout);
  },

  pingSucess: function(result, userContext, methodName) {
    var isTakeSurvey = window.location.pathname.toLowerCase().indexOf('takesurvey') !== -1;
    var isErrorPage =
      window.location.pathname.toLowerCase().indexOf('applicationerror') !== -1 ||
      window.location.pathname.toLowerCase().indexOf('takesurveyerror') !== -1;

    if (!isTakeSurvey && !isErrorPage && result !== NoviSurvey.Ping.prototype.sessionId) {
      window.location = NoviSurvey.Ping.prototype.errorPage;
    }
  }
}

NoviSurvey.Ping.registerClass('NoviSurvey.Ping', null, Sys.IDisposable);

// ----------- support for page methods -----------

function OnSucceededDoNothing(result, userContext, methodName) { }
function OnFailedDoNothing(error, userContext, methodName) { }

// ----------- generic functions -----------

function popupWindow(url, width, height, name, controlId) {
  //var params = 'height=' + height + ',width=' + width + ',scrollbars=yes, toolbar=yes, location=yes, status=yes, menubar=no, resizable=yes, dependent=no';
  var params = 'height=' + height + ',width=' + width + ',scrollbars=yes, toolbar=no, location=yes, status=yes, menubar=no, resizable=yes, dependent=no';

  var newWindow = window.open(
    url,
    name,
    params,
    true
  );
  if (newWindow) {
    newWindow.location = url;
    newWindow.focus();
  } else {
    if (controlId) {
      $get(controlId).style.visibility = 'visible';
      $get(controlId).style.display = 'inline';
    }
  }
}

function firstParent(node, tag) {
  while (node.tagName.toUpperCase() !== tag.toUpperCase() && node.parentNode) {
    node = node.parentNode;
  }
  return node.tagName.toUpperCase() === tag.toUpperCase() ? node : null;
}


function isWhiteSpace(node) {
  // Use ECMA-262 Edition 3 String and RegExp features
  return !(/[^\t\n\r ]/.test(node.data));
}

function isIgnorable(node) {
  // this function is used to ignore whitespace in the dom tree
  return (node.nodeType == 8) || // A comment node
         ((node.nodeType == 3) && isWhiteSpace(node)); // a text node, all ws
}

function firstChild(node, tag) {
  var res = node.firstChild;
  while (res) {
    if (!isIgnorable(res) && res.tagName.toUpperCase() == tag.toUpperCase()) break;
    res = res.nextSibling;
  }
  return res;
}

// Cross browser function to stop the propagation of an event
function stopEvent(evt) {
  if (!evt) evt = window.event;
  evt.cancelBubble = true;
  if (evt.stopPropagation) evt.stopPropagation();
}

function findItemPos(elem) {
  var curLeft = 0;
  var curTop = 0;
  if (!elem) {
    elem = window.event.srcElement;
  }
  if (elem.offsetParent != null) {
    curLeft = elem.offsetLeft;
    curTop = elem.offsetTop;
    var parent = elem.offsetParent;
    while (parent) {
      curLeft += parent.offsetLeft;
      curTop += parent.offsetTop;
      parent = parent.offsetParent;
    }
  }
  return [curLeft, curTop];
}

function superImposeDiv(divIdBottom, divIdTop) {
  var divBottom = $get(divIdBottom);
  var posBottom = findItemPos(divBottom);
  var divTop = $get(divIdTop);
  divTop.style.zIndex = parseInt(divBottom.style.zIndex) + 1;
  divTop.style.left = posBottom[0] + 'px';
  divTop.style.top = posBottom[1] + 'px';
  divTop.style.width = divBottom.offsetWidth + 'px';
  divTop.style.visibility = 'visible';
  // note: layer will not be transparent in IE7 if the div height is greater than 4094 px
  divTop.style.height = (divBottom.offsetHeight <= 4094 ? divBottom.offsetHeight : 4094) + 'px';
}

function copyToClipboard(inText) {
  if (window.clipboardData) {
    window.clipboardData.setData("Text", inText);
  }
  return false;
}

function findEventPosition(e) {
  if (!e) var e = window.event;

  var posx = e.clientX;
  var posy = e.clientY;

  return [posx, posy];
}

function scrollToTop() {
  window.document.body.scrollTop = 0;
  window.document.documentElement.scrollTop = 0;
}

function findChildrenButtons(parentNode) {
  var buttons = new Array();

  if (!parentNode) {
    return buttons;
  }

  var containers = new Array();
  containers.push(parentNode);

  while (containers.length > 0) {
    var curContainer = containers.pop();

    for (var i = 0; i < curContainer.childNodes.length; i++) {
      var curNode = curContainer.childNodes[i];
      if (curNode.tagName && curNode.tagName.toUpperCase() === 'INPUT' &&
          (curNode.type.toUpperCase() === 'RADIO' || curNode.type.toUpperCase() === 'CHECKBOX')) {
        buttons.push(curNode);
      } else if (curNode.childNodes.length > 0) {
        containers.push(curNode);
      }
    }
  }

  return buttons;
}

// ----------- Caret position in text field -----------

function getCaretPosition(control) {
  var caretPos = 0;
  // IE
  if (document.selection) {
    control.focus();
    var sel = document.selection.createRange();
    var sel2 = sel.duplicate();
    sel2.moveToElementText(control);
    caretPos = -1;
    while (sel2.inRange(sel)) {
      sel2.moveStart('character');
      caretPos++;
    }
  }
  // Firefox
  else if (control.selectionStart || control.selectionStart == '0') {
    caretPos = control.selectionStart;
  }
  return (caretPos);
}

function setCaretPosition(control, position) {
  // IE
  if (control.setSelectionRange) {
    control.focus();
    control.setSelectionRange(position, position);
  }
  // Firefox
  else if (control.createTextRange) {
    var range = control.createTextRange();
    range.collapse(true);
    range.moveEnd('character', position);
    range.moveStart('character', position);
    range.select();
  }
}

// ----------- wait tooltip -----------

function showWaitTooltip(e) {
  var pos = findEventPosition(e);
  var dt = $get('clickDiv');
  dt.style.visibility = 'visible';
  dt.style.display = 'block';

  var x = pos[0] - dt.offsetWidth / 2 - 1;
  var y = pos[1] - dt.offsetHeight - 1;

  dt.style.left = x + 'px';
  dt.style.top = y + 'px';
  setTimeout('hideWaitTooltip(' + x + ',' + y + ')', 1000);
}

function hideWaitTooltip(x, y) {
  var dt = $get('clickDiv');
  if (dt.offsetLeft === x && dt.offsetTop === y || dt.offsetLeft === 0 || dt.offsetTop === 0) {
    dt.style.visibility = 'hidden';
    dt.style.display = 'none';
  }
}

// ----------------------------------------------------
// Button user control

function btn_onmousedown(path, btn_left, btn_right, btn_center) {
  $get(btn_left).src = path + 'Images/button_blue_down_l.png';
  $get(btn_right).src = path + 'Images/button_blue_down_r.png';
  $get(btn_center).style.backgroundImage = 'url(' + path + 'Images/button_blue_down_bg.png)';
  $get(btn_center).style.cursor = 'default';
  $get(btn_center).style.color = '#0066AA';
}

function btn_onmouseup(path, btn_left, btn_right, btn_center) {
  $get(btn_left).src = path + 'Images/button_blue_l.png';
  $get(btn_right).src = path + 'Images/button_blue_r.png';
  $get(btn_center).style.backgroundImage = 'url(' + path + 'Images/button_blue_bg.png)';
  $get(btn_center).style.cursor = 'default';
  $get(btn_center).style.color = '#0066AA';
}

function btn_onmouseover(path, btn_left, btn_right, btn_center) {
  $get(btn_left).src = path + 'Images/button_blue_l.png';
  $get(btn_right).src = path + 'Images/button_blue_r.png';
  $get(btn_center).style.backgroundImage = 'url(' + path + 'Images/button_blue_bg.png)';
  $get(btn_center).style.cursor = 'pointer';
  $get(btn_center).style.color = '#0066AA';
}

function btn_onmouseout(path, btn_left, btn_right, btn_center) {
  $get(btn_left).src = path + 'Images/button_blue_l.png';
  $get(btn_right).src = path + 'Images/button_blue_r.png';
  $get(btn_center).style.backgroundImage = 'url(' + path + 'Images/button_blue_bg.png)';
  $get(btn_center).style.cursor = 'default';
  $get(btn_center).style.color = 'white';
}

function btn_ondblclick() {
  if (document.selection) {
    document.selection.empty();
  }
}

function btn_click(btnID, chkID) {
  $get(btnID).click();
}

// --------------------------------------
//  RibbonIconCtl 

function VertIconMouseOver(path, leftImageId, rightImageId) {
  $get(leftImageId).src = path + 'Images/ribbon_vert_icon_bg_hover_l.png';
  $get(rightImageId).src = path + 'Images/ribbon_vert_icon_bg_hover_r.png';
}

function VertIconMouseOut(path, leftImageId, rightImageId) {
  $get(leftImageId).src = path + 'Images/ribbon_vert_icon_bg_l.png';
  $get(rightImageId).src = path + 'Images/ribbon_vert_icon_bg_r.png';
}

function VertIconDblClick() {
  if (document.selection) {
    document.selection.empty();
  }
}

function VertIconClick(btnID) {
  $get(btnID).click();
}

function HorizIconMouseOver(path, leftImageId, rightImageId) {
  $get(leftImageId).src = path + 'Images/ribbon_horiz_icon_bg_hover_l.png';
  $get(rightImageId).src = path + 'Images/ribbon_horiz_icon_bg_hover_r.png';
}

function HorizIconMouseOut(path, leftImageId, rightImageId) {
  $get(leftImageId).src = path + 'Images/ribbon_horiz_icon_bg_l.png';
  $get(rightImageId).src = path + 'Images/ribbon_horiz_icon_bg_r.png';
}

function HorizIconDblClick() {
  if (document.selection) {
    document.selection.empty();
  }
}

function HorizIconClick(btnID, iconImageId) {
  $get(iconImageId).style.cursor = 'default';
  $get(iconImageId).title = '';
  exeHandler(
    function() {
      var btn = $get(btnID);
      if (btn.click) {
        btn.click();
      }
    }
  );
}

function exeHandler(handler) {
  var prm = Sys.WebForms.PageRequestManager.getInstance();

  if (prm.get_isInAsyncPostBack()) {
    var handlerExecuted = false;
    var singleExeHandler = function(sender, args) {
      if (!handlerExecuted) {
        handler(sender, args);
      }
      handlerExecuted = true;
    };
    prm.add_endRequest(singleExeHandler);
  } else {
    handler();
  }
}

function HidePanel(panelId, fieldId) {
  var panel = $get(panelId);
  panel.style.visibility = 'hidden';
  panel.style.display = 'none';
  var field = $get(fieldId);
  field.value = "collapsed";
}

function centerDiv(df) {
  var dfs = df.style;
  var offsetW = -154 / 2;
  var offsetH = -52 / 2;
  dfs.position = 'absolute';
  dfs.zIndex = 999999999;
  if (window.innerWidth) {
    var hCenter = window.innerWidth / 2;
    var vCenter = window.innerHeight / 2;
    dfs.left = hCenter + offsetW + "px";
    dfs.top = vCenter + offsetH + "px";
  }
  else {
    var hCenter = document.documentElement.clientWidth / 2;
    var vCenter = document.documentElement.clientHeight / 2;
    dfs.left = hCenter + offsetW + "px";
    dfs.top = vCenter + offsetH + "px";
  }
}

function centerUpdateProgress(updateProgressId) {
  var windowHandler = function() { centerDiv($get(updateProgressId)); };

  window.onload = windowHandler;
  window.onresize = windowHandler;
  window.onscroll = windowHandler;
}

function RegisterUpdateProgress(panelId) {
  var panel = $get(panelId);
  function ShowUpdateProgress() {
    panel.style.visibility = 'visible';
    panel.style.display = 'block';
  }
  function HideUpdateProgress() {
    panel.style.visibility = 'hidden';
    panel.style.display = 'none';
  }
  Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(ShowUpdateProgress);
  Sys.WebForms.PageRequestManager.getInstance().add_endRequest(HideUpdateProgress);
}

//-------------------------------------------------------------------------------------------
// TextEditorControl functions

function ShowEditor(titleID, titleTxt, modalID, uEditorID, textBoxID, panelHiddenFieldID, uEditorTextBoxID) {
  var title = $get(titleID);
  var modal = $find(modalID);
  var uEditor = UltimateEditors[uEditorID];
  var uEditorTextBox = $get(uEditorTextBoxID);
  var textBox = $get(textBoxID);
  var panelHiddenField = $get(panelHiddenFieldID);
  title.innerHTML = titleTxt;
  uEditor.SetEditorHTML(textBox.value);
  uEditorTextBox.style.position = 'relative';
  uEditorTextBox.style.zIndex = '9999';
  panelHiddenField.value = textBoxID;
  modal.show();
}

function SaveEditor(uEditorID, panelHiddenFieldID) {
  var uEditor = UltimateEditors[uEditorID];
  var panelHiddenField = $get(panelHiddenFieldID);
  var textBox = $get(panelHiddenField.value);
  textBox.value = uEditor.GetEditorHTML();
}

function ShowCallOut(divID, calloutContentID, textBoxID) {
  var calloutContent = $get(calloutContentID)
  var textBox = $get(textBoxID);
  var div = $get(divID);
  if (textBox.value != null && textBox.value.match('<') == '<') {
    calloutContent.innerHTML = textBox.value;
    var pos = findItemPos(textBox);
    div.style.left = pos[0] + "px";
    div.style.top = pos[1] + 22 + "px";
    div.style.visibility = 'visible';
    div.style.display = 'inline';
  }
}

function HideCallOut(divID) {
  var div = $get(divID);
  div.style.visibility = 'hidden';
  div.style.display = 'none';
}

//-------------------------------------------------------------------------------------------
