dojo.provide("parus.parus8");

dojo.require("dojo.DeferredList");
dojo.require("dojo.colors");
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("dojo.dom");
dojo.require("dojo.mouse");

dojo.require("dijit.place");
dojo.require("dijit.Viewport");
dojo.require("dijit._Templated");
dojo.require("dijit.MenuItem");
dojo.require("dijit.Tree");
dojo.require("dijit.Editor");
dojo.require("dijit._editor.range");
dojo.require("dijit._editor.plugins.FontChoice");
dojo.require("dijit._editor._Plugin");
dojo.require("dijit._editor.plugins.AlwaysShowToolbar");
dojo.require("dijit._editor.plugins.FontChoice");
dojo.require("dijit._editor.plugins.TextColor");
dojo.require("dijit._editor.plugins.LinkDialog");
dojo.require("dijit._editor.plugins.ViewSource");

dojo.require("dojox.grid.DataGrid");
dojo.require("dojox.grid.EnhancedGrid");
dojo.require("dojox.grid.Selection");
dojo.require("dojox.grid._Grid");
dojo.require("dojox.grid._Builder");
dojo.require("dojox.grid.cells.dijit");
dojo.require("dojox.grid.enhanced.plugins.IndirectSelection");

dojo.require("parus.database");
dojo.require("parus.loginDialog");
dojo.require("parus.errorMessageDialog");
dojo.require("parus.notificationDialog");

dojo.require("parus.embeddedMode");

dojo.require("parus.parusBrowserValidator");


if (!parus) parus = {};

if (!parus.parus8) dojo.mixin(parus, {
  parus8: {}
});

dojo.mixin(parus.parus8, {

  CLASS_ParusBalanceContentHandler: "{8B137980-B315-46EE-8553-7E08C991ECDB}",
  //Balance
  CLASS_PPCBalanceContentHandler: "{E9E27219-4C6D-4EC7-B272-718858A9E258}",
  //Balance
  CLASS_FolderContentHandler: "{3EE433E6-8FE9-4471-A972-561725956DCC}",

  CLASS_OCIProxyParusBalanceContentHandler: "{62F90CA0-67AA-41BC-8954-052FAE60056A}",
  //Balance ЦУД
  CLASS_PPCProxyBalanceContentHandler: "{B49A47C4-1FE1-4678-BBD2-F2EA86F4B514}",
  //Balance ЦУД
  CLASS_InstantMessageHandler: "{95DB70D3-9FC4-4721-8FD8-8B7EF0CB9E28}",

  parusClientLauncherFileName: "ParusClient.exe",

  CLASS_EmptyData: "{27BC9534-FD41-4DF5-89B5-DEC3AC0D28C0}",

  version: {
    major: 0,
    minor: 0,
    patch: 0,
    flag: ".0",
    revision: "develop",
    toString: function() {
      var v = parus.parus8.version;
      return v.major + "." + v.minor + "." + v.patch + v.flag + " (" + v.revision + ")"; // String
    }
  },

  _hasInstantMessagesHandler: null,

  _SSLCertAuthSubDomain: null,

  _colorNames: {},

  _sessionUsed: false,

  _login_url: null,

  _themeEditorMode: false,

  _embeddedMode: false,

  _clientSessionTimeout: 0,

  _clientSessionTimeoutID: null,

  _sysColors: {
    "-2147483648": [212, 208, 200],
    "-2147483647": [0, 78, 152],
    "-2147483646": [0, 84, 227],
    "-2147483645": [122, 150, 223],
    "-2147483644": [255, 255, 255],
    "-2147483643": [255, 255, 255],
    "-2147483642": [0, 0, 0],
    "-2147483641": [0, 0, 0],
    "-2147483640": [0, 0, 0],
    "-2147483639": [255, 255, 255],
    "-2147483638": [212, 208, 200],
    "-2147483637": [212, 208, 200],
    "-2147483636": [128, 128, 128],
    "-2147483635": [49, 106, 197],
    "-2147483634": [255, 255, 255],
    "-2147483633": [236, 233, 216],
    "-2147483632": [172, 168, 153],
    "-2147483631": [172, 168, 153],
    "-2147483630": [0, 0, 0],
    "-2147483629": [216, 228, 248],
    "-2147483628": [255, 255, 255],
    "-2147483627": [113, 111, 100],
    "-2147483626": [241, 239, 226],
    "-2147483625": [0, 0, 0],
    "-2147483624": [255, 255, 225],
    "-2147483622": [0, 0, 128],
    "-2147483621": [61, 149, 255],
    "-2147483620": [157, 185, 235],
    "-2147483619": [49, 106, 197],
    "-2147483618": [236, 233, 216]
  },

  _themes: null,

  _intfs: null,

  startup: function(task, startupObject, alreadyLogged) {

    var bs = dojo.cookie("bs");
    var bc = dojo.cookie("bc");

    if (!parus.parus8._themes) {
      parus.parus8._themes = [];

      var found = false;

      if (!this._themeEditorMode) dojo.xhrGet({
        url: dojo.moduleUrl("parus", "theme/themes.xml").toString(),
        handleAs: "xml",
        sync: true,
        preventCache: true,
        load: function(response) {
          if (!dojo.isIE) response.normalize();
          parus.parus8._themes = [];
          var nodes = response.documentElement.getElementsByTagName("theme");
          for (var i = 0; i != nodes.length; i++) {
            parus.parus8._themes.push(nodes[i]);
            if (nodes[i].getAttribute("id") == (bc || "").split(" ")[0]) found = true;
          }
          return response;
        }
      });

      if (!found) bc = null;

      for (var i = 0; i < parus.parus8._themes.length; i++)
      if (parus.parus8._themes[i].getAttribute("loaded") != "1") {
        dojo.place("<link type=\"text/css\" rel=\"stylesheet\" href=\"" + "../parusjs/theme/" + parus.parus8._themes[i].getAttribute("id") + "/theme.css" + "\" >" + "</link>", document.getElementsByTagName("head")[0], "last");
      };
    };


    if (!parus.parus8._intfs) {
      parus.parus8._intfs = [];
      var found = false;

      dojo.xhrGet({
        url: dojo.moduleUrl("parus", "intf.xml").toString(),
        handleAs: "xml",
        sync: true,
        preventCache: false,
        load: function(response) {
          if (!dojo.isIE) response.normalize();
          parus.parus8._intfs = [];
          var nodes = response.documentElement.getElementsByTagName("schema");
          for (var i = 0; i != nodes.length; i++) {
            parus.parus8._intfs.push({
              id: nodes[i].getAttribute("id"),
              title: nodes[i].getAttribute("title")
            });
            if (nodes[i].getAttribute("id") == bs) found = true;
          }
          return response;
        }
      });

      if (!found) bs = null;

    };

    if (!parus.parus8._SSLCertAuthSubDomain || !parus.parus8._hasInstantMessagesHandler) {
      dojo.xhrGet({
        handleAs: "xml",
        sync: true,
        headers: {
          "Disable-Basic-Auth": "yes"
        },
        preventCache: true,
        url: "../.system/contents.xml",
        load: dojo.hitch(this, function(response) {
          for (var i = 0; i < response.documentElement.childNodes.length; i++) {
            var node = response.documentElement.childNodes[i];
            if ((node.getAttribute("disabled") || 0).toString() == "1") continue;

            if ((node.getAttribute("class").toString() == parus.parus8.CLASS_InstantMessageHandler.toString())) {
              parus.parus8._hasInstantMessagesHandler = node.getAttribute("ID");
            }
            else if (((node.getAttribute("class").toString() == parus.parus8.CLASS_ParusBalanceContentHandler.toString()) || (node.getAttribute("class").toString() == parus.parus8.CLASS_PPCBalanceContentHandler.toString()))) {

              if (node.getAttribute("SSLCertAuthSubDomain")) {
                var domain = node.getAttribute("SSLCertAuthSubDomain");
                if (!domain.startsWith("https://")) domain = "https://" + domain;
                if (domain.endsWith("/")) domain = domain.substring(0, domain.length - 1);
                parus.parus8._SSLCertAuthSubDomain = domain;
              }
            }
          }
          return (response);
        })
      });
    }

    document.body.className = bc || document.body.className;

    if (!alreadyLogged) startupObject = parus[bs] || startupObject;

    if (dojo.isTrident) dojo.addClass(dojo.body(), "ie11");
    //    if (dojo.isEdge) dojo.addClass(dojo.body(), "edge");
    this._colorNames = dojo.i18n.getLocalization("dojo", "colors") || this._colorNames;

    var sessionAuthorized = null;
    var sessionUserName = null;
    var sessionUserHandler = null;
    var sessionPassword = null;
    var sessionNegotiate = null;
    var sessionSSLCert = null;

    var sessionUserNameC = false;
    var sessionUserHandlerC = false;
    var sessionPasswordC = false;
    var sessionNegotiateC = false;
    var sessionOpenID = false;

    var sessionSSLCertC = false;

    var login_url = null;

    var isEmbeddedMode = false;

    var sessionContent = {};

    var sessionProc = function() {
      dojo.xhrGet({
        handleAs: "xml",
        sync: true,
        preventCache: true,
        content: {
          jsversion: (dojo.version ? dojo.version.toString() : "") || ""
        },
        url: "../.system/session.xml",
        load: function(response) {
          var LNodes = response.documentElement.getElementsByTagName("*");
          for (var i = 0; i != LNodes.length; i++) {
            sessionContent[LNodes[i].nodeName] = LNodes[i].childNodes.item(0).nodeValue;

            if ((LNodes[i].nodeName == "SessionWasAuthorized")) sessionAuthorized = LNodes[i].childNodes.item(0).nodeValue;

            else if ((LNodes[i].nodeName == "loggedUserName")) {
              sessionUserName = LNodes[i].childNodes.item(0).nodeValue;
              sessionUserNameC = (LNodes[i].getAttribute("Source") != "3");
            }
            else if ((LNodes[i].nodeName == "loggedUserHandler")) {
              sessionUserHandler = LNodes[i].childNodes.item(0).nodeValue;
              sessionUserHandlerC = (LNodes[i].getAttribute("Source") != "3");
            }
            else if ((LNodes[i].nodeName == "loggedUserPassword")) {
              sessionPassword = LNodes[i].childNodes.item(0).nodeValue;
              sessionPasswordC = (LNodes[i].getAttribute("Source") != "3");
            }
            else if ((LNodes[i].nodeName == "loggedAsNegotiate-c")) {
              sessionNegotiate = LNodes[i].childNodes.item(0).nodeValue;
              sessionNegotiateC = (LNodes[i].getAttribute("Source") != "3");
            }
            else if ((LNodes[i].nodeName == "loggedAsSSLCert-c")) {
              sessionSSLCert = LNodes[i].childNodes.item(0).nodeValue;
              sessionSSLCertC = (LNodes[i].getAttribute("Source") != "3");
            }

            else if ((LNodes[i].nodeName == "openid.mode")) sessionOpenID = true;
            else if ((LNodes[i].nodeName == "login_url")) login_url = LNodes[i].childNodes.item(0).nodeValue;

            if (LNodes[i].nodeName == "embeddedMode") isEmbeddedMode = true;
          }
          return (response);
        }
      });
    };

    sessionProc();

    this._sessionUsed = sessionAuthorized == "1" || !! (sessionUserHandlerC && (sessionUserNameC && sessionPasswordC));
    this._login_url = login_url;

    sessionUserName = sessionUserName || dojo.cookie("loggedUserName-c");
    sessionUserHandler = sessionUserHandler || dojo.cookie("loggedUserHandler-c");
    sessionPassword = sessionPassword || dojo.cookie("loggedUserPassword-c");
    sessionNegotiate = sessionNegotiate || dojo.cookie("loggedAsNegotiate-c");
    sessionSSLCert = sessionSSLCert || dojo.cookie("loggedAsSSLCert-c");

    var connected = dojo.hitch(this, function() {
      setTimeout(dojo.hitch(this, function() {

        if (!bc && (!parus.parus8._themeEditorMode)) {
          var className = (parus.parus8._themes[(parus.database.attributes.defaultSchema % parus.parus8._themes.length)].getAttribute("id") || "parus8");
          var zoomClass = (parus.database.attributes.defaultZoom == "1") ? "z125" : (parus.database.attributes.defaultZoom == "2") ? "z150" : "z100";
          if (dojo.isEdge || dojo.isIE) zoomClass = "z100";
          document.body.className = ([className, zoomClass]).join(" ");
        }

        if (!alreadyLogged && !bs) {
          startupObject = parus[(dojo.map(parus.parus8._intfs, function(intf) {
            return intf.id
          }))[Math.floor(parus.database.attributes.defaultSchema / parus.parus8._themes.length)]] || startupObject;
        }

        if (isEmbeddedMode) parus.embeddedMode.startup(sessionContent);

        parus.userdata.load();
        startupObject.startup(sessionContent);

        if ((parus.database.attributes["auth-userCanRecieveMessages"] == "1") && parus.parus8._hasInstantMessagesHandler) {

          var messages = new mill.InstantMessages({
            handler: parus.parus8._hasInstantMessagesHandler,
            pollTimeout: dojo.number.parse(parus.parus8.optionValue("InstantMessagePoolingIntervalWeb")) * 1000
          }, dojo.place("<div></div>", dojo.body(), "last"));
          messages.startup();

        }

        var parusSessionTimeOut = parseInt(parus.database.attributes["parusSessionTimeOut"]);
        if (undefined === parusSessionTimeOut || isNaN(parusSessionTimeOut)) {
          parusSessionTimeOut = 0;
        }
        if (parusSessionTimeOut > 0) {
          this.keepAliveSession(parusSessionTimeOut);
        }

        if ((!parus.parus8._themeEditorMode) && !isEmbeddedMode) {
          this._clientSessionTimeout = parseInt(parus.parus8.optionValue("BalanceOnlineClientTimeout")) || 0;
          this.registerAction();
        }

      }), 500);
    });

    var justClosed = parseInt(dojo.cookie("justClosed"));

    /*var is2FactorAuth = sessionContent.hasOwnProperty("auth-is2FactorAuth") && sessionContent["auth-is2FactorAuth"] == "1";
     var sessionAuthorizedBySSLCert = parus.parus8._SSLCertAuthSubDomain
     && sessionContent.hasOwnProperty("auth-SSLCert_auth_Verified") && sessionContent["auth-SSLCert_auth_Verified"] == "1"
     && sessionContent.hasOwnProperty("auth-SSLCert_AssociatedUserName") && sessionContent["auth-SSLCert_AssociatedUserName"] != "";
     var sessionAuthorized =  (sessionAuthorized == "1"
     || sessionOpenID
     || ((sessionSSLCert == "1" || is2FactorAuth) && sessionAuthorizedBySSLCert));*/

    //сессия авторизована - заходим молча
    if (sessionUserHandler && (alreadyLogged || (sessionAuthorized == "1" && !justClosed)) && parus.database.connect(sessionUserHandler, null, null)) {
      connected();
      return;
    }
    //есть сохраненные реквизиты - авторизуемся используя их
    else if (sessionUserHandler && sessionUserName && sessionPassword && !justClosed && parus.database.connect(sessionUserHandler, sessionUserName, sessionPassword)) {
      connected();
      return;
    }
    else {

      var doLoginDialog = function() {

        dojo.cookie("justClosed", "");
        setTimeout(function() {

          var dialog = new parus.loginDialog({
            task: task,
            sessionUserName: sessionUserName,
            sessionUserHandler: sessionUserHandler,
            sessionPassword: sessionPassword,
            sessionNegotiate: sessionNegotiate,
            sessionSSLCert: sessionSSLCert,

            onApply: function() {
              loadingDiv.style.display = "";
              connected();
              return true;
            }
          });

          loadingDiv.style.display = "none";
          dialog.show();

        }, 100);


      };

      if (parus.parus8._messageWindow) {

        parus.parus8._messageWindow.onClose = function() {
          parus.parus8._messageWindow = null;
          doLoginDialog();
        }

      }
      else {
        doLoginDialog();


      }


    }


  },

  unimplemented: function(object, APIName, args) {
    console.log("Unimplemented API: " + (object.declaredClass || "parus.parus8") + "." + APIName, args);
    throw new Error("Unimplemented API: " + (object.declaredClass || "parus.parus8") + "." + APIName);
  },

  rowNodes: function(response) {

    if (dojo.isArray(response)) return response;
    if (!response) return [];
    var nodes = (response.documentElement) ? response.documentElement.childNodes : response.childNodes;
    var result = new Array();
    for (var i = 0, len = nodes.length; i < len; i++)
    if (nodes[i]) if (nodes[i].nodeType == 1) if (nodes[i].nodeName.toUpperCase() != "SCRIPT") //Парус-1522
    result.push(nodes[i]);
    return result;
  },

  _mapFields: function(node) {

    var _fieldsMap;

    if (node && !dojo.isIE) _fieldsMap = node._fieldsMap;

    if (_fieldsMap) return _fieldsMap;

    _fieldsMap = {};

    if (node) {

      var nodes = node.childNodes;

      if (nodes) {


        for (var i = 0, len = nodes.length; i < len; i++) {
          var value = nodes[i].firstChild;
          if (value && value.nodeType) {
            if (value.nodeType == 3) value = value.nodeValue;
            else if (value.nodeType == 1) value = this.rowNodes(value)
          };
          _fieldsMap[nodes[i].nodeName] = value;
        }

        if (!dojo.isIE) dojo.mixin(node, {
          _fieldsMap: _fieldsMap
        });

      }
      else _fieldsMap = node;


    }

    return _fieldsMap;
  },

  nodeField: function(node, fieldName) {
    return node ? (node.nodeType ? this._mapFields(node)[fieldName] : node[fieldName]) : node;
  },

  catalogTreeGetLabelClass: function(item, opened) {
    if ((parus.parus8.nodeField(item, "ISVALID") != "1") && ((parus.parus8.nodeField(item, "NAME") == "Каталог недоступен") || (parus.parus8.nodeField(item, "NAME") == "Папка недоступна"))) return "dijitHiddenItem"
    else if (this.listMode) return "dijitListedItem";
  },

  catalogTreeGetIconClass: function(item, opened) {
    if (this.listMode) return "dijitFolderListed"
    else if (parus.parus8.nodeField(item, "ISVALID") != "1") return ("dijitFolderDisabled")
    else return ( !! opened ? "dijitFolderOpened" : "dijitFolderClosed");
  },

  folderTreeGetIconClass: function(item, opened) {
    if (parus.parus8.nodeField(item, "ISVALID") != "1") return ("dijitYellowFolderDisabled")
    else if (parus.parus8.nodeField(item, "SOURCE") != "2") return ("dijitYellowFolderDisabled")
    else return ( !! opened ? "dijitYellowFolderOpened" : "dijitYellowFolderClosed");
  },

  compareNodes: function(node1, node2) {
    if (dojo.isIE) return node1.sourceIndex == node2.sourceIndex;
    else return (node1.compareDocumentPosition(node2) == 0);
  },

  monthNames: function() {
    return ["Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"];
  },

  internalLogout: function() {

    if (this._keepAliveSessionTimeout) {
      clearTimeout(this._keepAliveSessionTimeout);
      this._keepAliveSessionTimeout = null;
    };

    if (this._clientSessionTimeoutID) {
      clearTimeout(this._clientSessionTimeoutID);
      this._clientSessionTimeoutID = null;
    };

    if (this._notificationTimeout) {
      clearTimeout(this._notificationTimeout);
      this._notificationTimeout = null;
    }

    parus.database.clearSessionIdent();

    if (this._sessionUsed || !document.referrer || (document.referrer != document.location.pathname)) dojo.cookie("justClosed", "1");

    parus.database.connected = null;

    parus.database.attributes = null;

    parus.database.login = null;

    parus.database.authException = null;

    parus.database.companyName = null;

    var url = (this._login_url) ? this._login_url : (this._sessionUsed) ? document.location.pathname : (document.referrer || document.location.pathname);

    window.open(url, "_self");
  },

  logout: function() {
    if (parus.parus8._embeddedMode) {
      parus.embeddedMode.closeTab();
      return;
    };

    dojo.xhrGet({
      url: parus.database.getLogoutUrl(),
      handleAs: "xml",
      sync: true,
      preventCache: true
    });

    parus.parus8.internalLogout(); //this.internalLogout(); <- this. may be a window
  },

  _keepAliveSessionTimeout: null,
  _keepAliveSessionDisabled: false,

  keepAliveSession: function(time) {
    var CMinTimeOut = 60;

    if (this._keepAliveSessionTimeout) {
      clearTimeout(this._keepAliveSessionTimeout);
      this._keepAliveSessionTimeout = null;
    }

    var setTimeOutProc = dojo.hitch(this, function(time) {
      time = (time - 60) > 0 ? (time - 60) : CMinTimeOut;
      this._keepAliveSessionTimeout = setTimeout(dojo.hitch(this, this.keepAliveSession), time * 1000);
    });

    if (time) {
      setTimeOutProc(time);
    }
    else {
      parus.database.query("keepAliveSessionQuery", {}, dojo.hitch(this, function(response) {
        if (this._keepAliveSessionDisabled) return;

        var LValue = parseInt(parus.parus8.nodeField(parus.parus8.rowNodes(response)[0], "TIME_LEFT"));
        if (undefined === LValue || isNaN(LValue)) {
          LValue = CMinTimeOut;
        }
        setTimeOutProc(LValue);
      }), dojo.hitch(this, function(e) {
        if (e.status === 403) {
          //parus.database.connected = null;
          console.log("Session is unauthorized - disable session keep alive", e);
          this._keepAliveSessionDisabled = true;
        }
        else setTimeOutProc(CMinTimeOut);
      }), true);
    }
  },

  registerAction: function() {
    if (this._clientSessionTimeoutID) clearTimeout(this._clientSessionTimeoutID);
    this._clientSessionTimeoutID = null;
    if (this._clientSessionTimeout) this._clientSessionTimeoutID = setTimeout(dojo.hitch(this, this.logout), this._clientSessionTimeout * 1000);
  },

  formatBoolean: function(data, rowIndex, column) {
    return (["Нет", "Да"])[data];
  },

  formatFloat: function(data, rowIndex, column) {
    if (data) {
      var n = dojo.number.parse((data.toString()).split(".").join(","));
      return isNaN(n) ? data : dojo.number.format(n, {
        pattern: "#,##0.########################################"
      })
    }
    else return data;
  },


  formatFloatIntFrac: function(data) {

    return (this.fracPart ? data ? parus.parus8.formatIndexConsValue((data.toString()).split(".").join(","), this.intPart, this.fracPart) : data : parus.parus8.formatFloat(data));
  },

  formatWrappedText: function(data, rowIndex, column) {
    return data.split("\n").join("<br/>");
  },

  formatAuthType: function(data) {
    if (data == "Explicit") return "Логин/Пароль";
    else if (data == "OpenID") return "OpenID";
    else if (data == "Negotiate" || data == "NTLM") return "Доменная аутентификация Windows";
    else if (data == "SSLCert") return "Аутентификация по SSL сертификату";
    else return data;
  },

  formatCertDate: function(data, rowIndex, column) {
    return dojo.date.locale.format(data, {
      datePattern: "dd.MM.yyyy",
      timePattern: "HH:mm:ss"
    });
  },

  getXMLReportSignTemplateName: function(GOSTVersion, GOSTKeySize) {
    if (GOSTVersion == 2001) {
      return "reportSignTemplate.xml";
    }
    else if (GOSTVersion == 2012) {
      if (GOSTKeySize == 256) {
        return "reportSignTemplate_2012_256.xml";
      }
      else if (GOSTKeySize == 512) {
        return "reportSignTemplate_2012_512.xml";
      }
    }
    return "";
  },

  _messageWindow: null,

  errorMessage: function(message, onDone) {
    parus.parus8._messageWindow = new parus.errorMessageDialog({
      message: message.replace(/\n/g, "<br/>"),
      onClose: function() {
        parus.parus8._messageWindow = null;
        if (onDone) onDone();
      }
    });
    parus.parus8._messageWindow.show();
  },

  notificationMessage: function(message, onDone) {
    parus.parus8._messageWindow = new parus.notificationDialog({
      message: message.replace(/\n/g, "<br/>"),
      onClose: function() {
        parus.parus8._messageWindow = null;
        if (onDone) onDone();
      }
    });
    parus.parus8._messageWindow.show();
  },


  denote: function(ID, scope) {
    var result;
    dojo.forEach(ID.split("."), function(ID) {
      result = (result || scope || dojo.global)[ID];
    });
    return result;
  },

  compareObjects: function(obj1, obj2) {
    if (dojo.isArray(obj1) && (obj1.length == 1)) return parus.parus8.compareObjects(obj1[0], obj2)
    else if (dojo.isArray(obj2) && (obj2.length == 1)) return parus.parus8.compareObjects(obj1, obj2[0])
    else if (dojo.isObject(obj1) && dojo.isObject(obj2)) {
      if ((obj1.constructor == RegExp) || (obj2.constructor == RegExp)) return ( !! (obj1.toString() == obj2.toString()))
      else {
        var keys = [];
        for (var key in obj1)
        keys.push(key);
        for (var key in obj2)
        keys.push(key);
        var eq = true;
        dojo.every(keys, function(key) {
          if (!parus.parus8.compareObjects(obj1[key], obj2[key])) {
            eq = false;
            return eq;
          }
          else return true;
        });
        return eq;
      }
    }
    else return ( !! (obj1 == obj2));
  },

  getTextContent: function(node) {
    if (!node) return "";

    if (dojo.query("[rv]", node).length) {
      return dojo.query("[rv]", node)[0].getAttribute("rv");
    }
    else if (dojo.query("[rid='b']", node).length) {
      var text = node.innerHTML;
      text = text.split("<br rid=\"b\">").join("\n");
      text = text.split("<br rid=\"b\"/>").join("\n");
      text = text.split("<br rid=\"b\"></br>").join("\n");
      text = text.split("<BR rid=\"b\">").join("\n");
      text = text.split("<BR rid=\"b\"/>").join("\n");
      text = text.split("<BR rid=\"b\"></BR>").join("\n");
      return text;
    } else if (!dojo.isIE || dojo.isIE >= 10) {
      return node.textContent;
    }
    else {
      return node.innerText;
    }
  },

  styleSize: function(value) {
    var s = value.toString();
    s = s.substr(0, s.length - 2);
    return Number(s);
  },

  docAttrValue: function(item, docProp) {
    var rowNodes = parus.parus8.rowNodes(parus.parus8.nodeField(item, "XML_ATTRIBUTES"));
    if (!rowNodes) return null;
    if (!rowNodes.length) return null;
    return parus.parus8.nodeField(rowNodes[0], "S" + docProp);
  },

  docPropValue: function(item, docProp) {

    if (dojo.isIE <= 9) return parus.parus8.nodeField(item.selectSingleNode("XMLPROPERTIES/ROWSET/ROW[RN='" + docProp + "']"), "VALUE")
    else {
      var node = item.firstElementChild;

      while (node) {
        if (node.nodeName == "XMLPROPERTIES") {
          var nnode = node.firstElementChild ? node.firstElementChild.firstElementChild : null;
          while (nnode) {
            var nnnode = nnode.firstElementChild;
            while (nnnode) {
              if (nnnode.nodeName == "RN" && nnnode.firstChild.nodeValue == docProp) {
                var nnnnnode = nnode.firstElementChild;
                while (nnnnnode) {
                  if (nnnnnode.nodeName == "VALUE") return nnnnnode.firstChild.nodeValue;
                  nnnnnode = nnnnnode.nextElementSibling;
                }
              }
              nnnode = nnnode.nextElementSibling;
            }
            nnode = nnode.nextElementSibling;
          }
        }
        node = node.nextElementSibling;
      };
    }
  },

  optionValue: function(code) {
    var response = parus.database.execute("GetOptionValue", {
      CODE: code
    });
    return parus.parus8.nodeField(parus.parus8.rowNodes(response)[0], "VALUE");
  },

  hash: function(str) {
    str = dojo.trim(str);
    if (!str) return "";
    result = 0;
    for (var i = 0; i < str.length; i++) {
      result += str.charCodeAt(i);
    };
    return result.toString(16);
  },

  colorToCssColor: function(color) {

    var colorIndex = dojo.number.parse(color);
    var css = "";

    if (parus.parus8._sysColors[colorIndex]) {

      dojo.forEach(parus.parus8._sysColors[colorIndex], function(c) {
        var s = c.toString(16);
        while (s.length < 2)
        s = "0" + s;
        css = css + s;
      });

    }
    else {
      css = colorIndex.toString(16);
      while (css.length < 6)
      css = "0" + css;
      css = css.slice(4, 6) + css.slice(2, 4) + css.slice(0, 2);
    }

    return css;
  },

  formatColor: function(data, rowIndex, column) {

    var css = parus.parus8.colorToCssColor(data);
    var r = parseInt(css.slice(0, 2), 16);
    var g = parseInt(css.slice(2, 4), 16);
    var b = parseInt(css.slice(4, 6), 16);

    var colorName = "";

    for (var name in dojo.Color.named) {
      var arr = dojo.Color.named[name];
      if (arr[0] == r && arr[1] == g && arr[2] == b) colorName = name;
    };

    if (colorName) colorName = parus.parus8._colorNames[colorName] || colorName;

    if (!colorName) colorName = "#" + css.toUpperCase();

    return "<span style='width:18px;height:18px;border:1px solid black; background-color:" + css + "'>&#160;&#160;&#160;&#160;&#160;&#160;</span>&#160;&#160;" + colorName;
  },

  colorOptions: function() {

    var formatColor = function(value, name) {
      return "<div style='padding-top:2px;padding-bottom:2px'>" + "<span style='width:12px;height:12px;border:1px solid black; background-color:" + value + "'>&#160;&#160;&#160;&#160;&#160;&#160;</span>&#160;&#160;" + name + "</div>"
    };

    var options = [];

    for (var name in parus.parus8._colorNames) {
      if (dojo.Color.named[name]) {
        var r = dojo.Color.named[name][0];
        var g = dojo.Color.named[name][1];
        var b = dojo.Color.named[name][2];
        options.push({
          label: formatColor(name, parus.parus8._colorNames[name]),
          value: (b * 256 * 256 + g * 256 + r).toString()
        });
      }
    }
    return options;
  },

  formatRowNumber: function(data, rowIndex, column) {
    return (rowIndex + 1);
  },

  compareUntypedValues: function(a, b) {
    var va = a;
    var vb = b;

    var nva = dojo.number.parse(va.toString());
    var nvb = dojo.number.parse(vb.toString());

    if (!isNaN(nva) && !isNaN(nvb)) {
      va = nva;
      vb = nvb;
    }
    else {

      var done = false;
      dojo.forEach([{
        selector: "date",
        datePattern: "dd.MM.yyyy HH:mm:ss"
      },
      {
        selector: "date",
        datePattern: "dd.MM.yyyy HH:mm"
      },
      {
        selector: "date",
        datePattern: "dd.MM.yyyy"
      }], function(pattern) {
        if (done) return;
        var dva = dojo.date.locale.parse(va.toString(), pattern);
        var dvb = dojo.date.locale.parse(vb.toString(), pattern);
        if ( !! dva && !! dvb) {
          va = dva;
          vb = dvb;
          done = true;
        }
      });

    }

    if (va > vb) return 1;
    else if (va < vb) return -1;
    else return 0;

  },

  launcherFileName: "ParusClient.exe",

  installlerFileName: "ParusClientInstaller.exe",

  buildParusProxyLaunchersList: function(handlerClasses, path) {
    dojo.xhrGet({
      handleAs: "xml",
      sync: true,
      headers: {
        "Disable-Basic-Auth": "yes"
      },
      url: "../.system/contents.xml",
      load: dojo.hitch(this, function(response) {
        var launchersNode = document.getElementById("launchers");

        var found = false;
        for (var i = 0; i < response.documentElement.childNodes.length; i++) {
          var node = response.documentElement.childNodes[i];
          if ((handlerClasses.indexOf(node.getAttribute("class").toString()) >= 0) && ((node.getAttribute("disabled") || 0).toString() != "1")) {

            if (!found) {

              var paraNode = launchersNode.appendChild(document.createElement("p"));
              var linkNode = paraNode.appendChild(document.createElement("a"));
              linkNode.style.fontWeight = "bold";
              linkNode.style.fontSize = "120%";

              var appName = this.launcherFileName.split(".")[0];

              var iconNode = paraNode.appendChild(document.createElement("img"));
              iconNode.src = path + appName + ".ico";
              iconNode.align = "middle";
              iconNode.width = 16;
              iconNode.height = 16;
              linkNode.appendChild(iconNode);


              linkNode.appendChild(document.createTextNode(String.fromCharCode(160) + "Единый агент для всех доступных организаций и приложений"));
              linkNode.setAttribute("href", path + this.launcherFileName);

              paraNode = launchersNode.appendChild(document.createElement("p"));
              linkNode = paraNode.appendChild(document.createElement("a"));
              linkNode.style.fontWeight = "bold";
              linkNode.style.fontSize = "120%";

              appName = this.launcherFileName.split(".")[0];

              iconNode = paraNode.appendChild(document.createElement("img"));
              iconNode.src = path + appName + ".ico";
              iconNode.align = "middle";
              iconNode.width = 16;
              iconNode.height = 16;
              linkNode.appendChild(iconNode);

              linkNode.appendChild(document.createTextNode(String.fromCharCode(160) + "Инсталлятор системных компонент"));
              linkNode.setAttribute("href", path + this.installlerFileName);

              launchersNode.appendChild(document.createElement("hr"));
            }

            found = true;
          }
        };

        ((found) ? document.getElementById("noLaunchers") : launchersNode).style.display = "none";

        dojo.fadeIn({
          node: document.getElementById("remoteAccessInfo")
        }).play();

        return (response);
      })
    });
  },

  checkMenuSeparators: function(menu) {

    var checkMenu = function(menu) {

      var hasVisible = false;
      var separated = false;
      var lastSeparator = null;

      dojo.forEach(menu.getChildren(), function(menuItem) {

        if (menuItem.declaredClass == "dijit.MenuSeparator") {

          menuItem.domNode.style.display = separated ? "" : "none";

          if (separated) lastSeparator = menuItem;
          separated = false;



        }
        else {
          if (menuItem.popup) {
            menuItem.popup.from_item = menuItem;
            checkMenu(menuItem.popup);
          }

          if (menuItem.domNode.style.display != "none") {
            hasVisible = true;
            separated = true;
            lastSeparator = null;
          };

        }

        if (menuItem.toolBarButton) {
          menuItem.toolBarButton.attr("disabled", menuItem.disabled);
          menuItem.toolBarButton.domNode.style.display = menuItem.domNode.style.display;
        }

      });


      if (lastSeparator && !separated) lastSeparator.domNode.style.display = "none";

      if (menu.from_item) {
        menu.from_item.domNode.style.display = hasVisible ? "" : "none";
      }



    };

    checkMenu(menu);

    if (menu.actionsButtonPane) {
      if (menu.actionsButtonPane.toolbar) {
        var separated = false;
        dojo.forEach(menu.actionsButtonPane.toolbar.getChildren(), function(button) {
          if (button.declaredClass == "dijit.ToolbarSeparator") {
            button.domNode.style.display = separated ? "" : "none";
            separated = false;
          }
          else if (button.domNode.style.display != "none") separated = true;
        });
      };


      setTimeout(function() {
        dijit.byNode(menu.actionsButtonPane.domNode.parentNode).layout();
        menu.actionsButtonPane.layout();
      }, 400);


    }
  },

  getZoom: function() {
    if (dojo.hasClass(dojo.body(), "z150")) return 1.5
    else if (dojo.hasClass(dojo.body(), "z125")) return 1.25
    else return 1;
  },

  coords: function() {
    var ret = dojo.coords.apply(dojo, arguments);
    var z = parus.parus8.getZoom();
    ret.x = ret.x / z;
    ret.y = ret.y / z;
    return ret;
  },

  zoomContainerClass: function() {

    if (dojo.isFF || dojo.isOpera || dojo.isMozilla) return "mozZoomContainer";
    else return "zoomContainer";
  },

  _patternConditionRe: /\[[^\]]*\]/g,

  formatIndexConsValue: function(data, intpart, fracpart) {

    if (data) {
      var value = dojo.number.parse((data.toString()).split(".").join(","));

      if (isNaN(value)) return "";

      if (value && fracpart) {
        if (Math.abs(value) < Math.pow(10, -1 - fracpart)) value = 0;
        else value = dojo.number.round(value * Math.pow(10, fracpart)) / Math.pow(10, fracpart);
      };

      var result = dojo.number.format(value, {
        places: isNaN(parseInt(fracpart)) ? 100 : (parseInt(fracpart) || 0),
        group: " "
      });


      if (isNaN(parseInt(fracpart))) while (result.match(/.*,\d*0$/) || result.match(/.*,$/)) result = result.substring(0, result.length - 1);

      return result;

    }
    else return data;
  },

  formatExcelValue: function(value, format, textonly, intpart, fracpart) {
    if (value === null) return "";
    var vtype = typeof value;
    if (vtype == "number") {
      if (isNaN(value)) return "";


      var rvformat = null;
      if (parseInt(intpart)) {

        rvformat = "0";
        for (var i = 1; i < intpart; i++)
        rvformat = "#" + rvformat;
        if (parseInt(fracpart)) {
          rvformat = rvformat + ".";
          for (var i = 0; i < fracpart; i++)
          rvformat = rvformat + "0";
        }
      };

      if (value && fracpart) {
        if (Math.abs(value) < Math.pow(10, -1 - fracpart)) value = 0;
        else value = dojo.number.round(value * Math.pow(10, fracpart)) / Math.pow(10, fracpart)
      }

      var text = rvformat ? dojo.number.format(value, {
        pattern: rvformat,
        group: ""
      }) : value.toString().split(".").join(",");

      var attrs = ["rv=\"" + text + "\""];

      if (format) {

        var patternList = [];
        var currentPattern;
        var conditionResult = false;

        dojo.forEach(format.split(";"), function(pattern) {

          if (conditionResult) return;

          var conditions = pattern.match(parus.parus8._patternConditionRe);

          if (conditions) {

            var hasCondition = false;
            var conditionColor;

            dojo.forEach(conditions, function(condition) {
              pattern = pattern.split(condition).join("");

              condition = condition.substring(1, condition.length - 1);

              /*здесь темный момент. Надо как-то отличить условие и цвет*/
              var firstChar = condition.charAt(0);
              if (firstChar == "=") {
                condition = "=" + condition
                hasCondition = true;
              }
              else if ((firstChar != ">") && (firstChar != "<")) {
                conditionColor = condition;
                return;
              }
              else hasCondition = true;

              if (!conditionResult) {
                condition = condition.split(",").join(".");
                try {
                  conditionResult = dojo.fromJson((condition.indexOf("$") == -1) ? ("" + value.toString() + condition) : (condition.split("$").join(value.toString())));
                } catch (e) {};
              }

            });

            if (!hasCondition) patternList.push({
              pattern: pattern,
              color: conditionColor
            });

            else if (conditionResult) {
              currentPattern = {
                pattern: pattern,
                color: conditionColor
              }
            }

          }
          else patternList.push({
            pattern: pattern
          });
        });

        if (!currentPattern) {
          if (value > 0) currentPattern = patternList[0] || ""
          else if (value < 0) currentPattern = patternList[1] || {
            pattern: "-" + patternList[0].pattern,
            color: patternList[0].color
          } || "";
          else if (value = 0) currentPattern = patternList[2] || patternList[0] || "";
          else currentPattern = patternList[3] || patternList[0] || "";
        }

        if (currentPattern) {

          if (currentPattern.pattern.indexOf("@") != -1) text = currentPattern.pattern.split("@").join(text)
          else if (!currentPattern.pattern.match(dojo.number._numberPatternRE)) text = currentPattern.pattern;
          else if (currentPattern.pattern == "0") text = dojo.number.format(dojo.number.round(value));
          else {
            if ( /*(currentPattern.pattern.indexOf(".") >= 1) && */ (currentPattern.pattern.charAt(0) == "0")) currentPattern.pattern = "#" + currentPattern.pattern;
            else if ((currentPattern.pattern.charAt(0) == "-") && (currentPattern.pattern.charAt(1) == "0")) currentPattern.pattern = "-#" + currentPattern.pattern.substr(1);

            var r = /[\_]./;
            var m = r.exec(currentPattern.pattern);
            while (m) {
              currentPattern.pattern = currentPattern.pattern.replace(r, String.fromCharCode(160));
              m = r.exec(currentPattern.pattern);
            };

            currentPattern.pattern = currentPattern.pattern.split(" ").join(String.fromCharCode(160));
            text = dojo.number.format( /*(currentPattern.pattern.indexOf("-") == -1) ? value :*/ Math.abs(value), {
              pattern: currentPattern.pattern
            });
          }

          if (currentPattern.color) attrs.push("style=\"color:" + currentPattern.color + "\"");

        }
      }

      return textonly ? text : ("<span " + attrs.join(" ") + ">" + text + "</span>");
    }
    else if (vtype == "boolean") return value ? "ИСТИНА" : "ЛОЖЬ"
    else if (value.getDate) return dojo.date.locale.format(value, {
      selector: "date",
      datePattern: "dd.MM.yyyy"
    });
    else {
      var text = value.toString();
      return textonly ? text : text.replace(/\n/g, "<br rid=\"b\"/>");
    }
  },

  externalStringToValue: function(str, dataType) {
    if (!str) return null;
    if (dataType == "1") return dojo.number.parse(str.split(".").join(","));
    if (dataType == "2") return dojo.date.locale.parse(str, {
      selector: "date",
      datePattern: "dd.MM.yyyy"
    });
    return str;
  },

  valueToExternalString: function(value) {
    if (value === null) return "";
    var vtype = typeof value;
    if (vtype == "number") return isNaN(value) ? "" : (value.toString().indexOf("e") < 0 ? value.toString() : value.toFixed(15)).split(".").join(",")
    else if (vtype == "boolean") return value ? "ИСТИНА" : "ЛОЖЬ"
    else if (value.getDate) return dojo.date.locale.format(value, {
      selector: "date",
      datePattern: "dd.MM.yyyy"
    });
    else return value.toString();
  },


  aboutBox: function(onDone) {

    parus.database._xhr("aboutboxinfo.xml", null, null, function(response) {

      var content = [];

      content.push("<div style=\"margin-bottom:5px\">");
      content.push("Продукт: " + response.documentElement.getAttribute("parusproductname"));
      content.push("<div style=\"margin-left:5px;font-weight:normal;white-space: nowrap;\">");
      content.push("Версия: " + response.documentElement.getAttribute("parusmajor") + "." + response.documentElement.getAttribute("parusminor") + "." + response.documentElement.getAttribute("parusrelease") + "." + response.documentElement.getAttribute("parusbuild") + "<br/>");
      content.push("Редакция: " + response.documentElement.getAttribute("parusdate") + "<br/>");
      content.push("Регистрационный номер лицензии: " + response.documentElement.getAttribute("paruslicensenumber") + "<br/>");
      content.push("Регистрационный номер клиента: " + response.documentElement.getAttribute("parusclientnumber") + "<br/>");
      content.push("Наименование клиента: " + response.documentElement.getAttribute("parusclientname") + "<br/>");
      content.push("Индивидуальный номер налогоплательщика: " + response.documentElement.getAttribute("parusclientid") + "<br/>");
      content.push("Дата окончания лицензионного обслуживания: " + response.documentElement.getAttribute("paruslicenseenddate") + "<br/>");

      if (!parus.parus8._themeEditorMode) {

        content.push("<a target=\"_blank\" href=\"/" + parus.database._buildUrl("/license.pdf") + "\"><b>Лицензионное соглашение</b></a>");
      }
      content.push("</div>");
      content.push("</div>");


      content.push("<div style=\"margin-bottom:5px\">");
      content.push("Система управления базами данных:");
      content.push("<div style=\"margin-left:5px;font-weight:normal;white-space: nowrap;\">");
      content.push(response.documentElement.getAttribute("rdbms_desc"));

      content.push("Версия " + (response.documentElement.getAttribute("rdbms") == "Oracle" ? "OCI" : "LIBPQ") + ": " + response.documentElement.getAttribute("clientlib_major") + "." + response.documentElement.getAttribute("clientlib_minor") + "." + response.documentElement.getAttribute("clientlib_release") + "." + response.documentElement.getAttribute("clientlib_build") + "<br/>");
      content.push("</div>");
      content.push("</div>");

      content.push("<div style=\"margin-bottom:5px\">");
      content.push("Сервер приложений:");
      content.push("<div style=\"margin-left:5px;font-weight:normal;white-space: nowrap;\">");
      content.push("Версия: " + response.documentElement.getAttribute("major") + "." + response.documentElement.getAttribute("minor") + "." + response.documentElement.getAttribute("release") + "." + response.documentElement.getAttribute("build") + "<br/>");
      content.push("Редакция: " + response.documentElement.getAttribute("edition") + " (сборка " + response.documentElement.getAttribute("compiledate") + " " + response.documentElement.getAttribute("compiletime") + ")<br/>");

      content.push("Версия платформы: " + response.documentElement.getAttribute("millmajor") + "." + response.documentElement.getAttribute("millminor") + "." + response.documentElement.getAttribute("millrelease") + "." + response.documentElement.getAttribute("millbuild") + " (" + response.documentElement.getAttribute("millplatform") + ")<br/>");

      content.push("Операционная система: " + response.documentElement.getAttribute("Win32Platform") + "." + response.documentElement.getAttribute("Win32MajorVersion") + "." + response.documentElement.getAttribute("Win32MinorVersion") + "." + response.documentElement.getAttribute("Win32BuildNumber") + (response.documentElement.getAttribute("Win32CSDVersion") ? (" [" + response.documentElement.getAttribute("Win32CSDVersion") + "]") : "") + "<br/>");
      content.push("Расположение: " + response.documentElement.getAttribute("SysLocaleDefaultLCID") + "<br/>");
      content.push("Язык: " + response.documentElement.getAttribute("SysLocalePriLangID") + "-" + response.documentElement.getAttribute("SysLocaleSubLangID") + "<br/>");
      content.push("Кодовая страница: " + response.documentElement.getAttribute("DefaultSystemCodePage") + "-" + response.documentElement.getAttribute("DefaultUnicodeCodePage") + "<br/>");
      content.push("Версия Microsoft Office: " + response.documentElement.getAttribute("excel"));

      content.push("</div>");
      content.push("</div>");


      content.push("<div style=\"margin-bottom:5px\">");
      content.push("Браузер:");
      content.push("<div style=\"margin-left:5px;font-weight:normal;white-space: nowrap;\">");

      dojo.forEach([{
        key: "appName",
        name: "Наименование приложения"
      },
      {
        key: "language",
        name: "Язык"
      },
      {
        key: "oscpu",
        name: "Операционная система"
      },
      {
        key: "platform",
        name: "Платформа"
      },
      {
        key: "product",
        name: "Продукт"
      },
      {
        key: "userAgent",
        name: "UserAgent"
      }], function(param) {

        try {
          var value = window.navigator[param.key];
          if (value) {
            if (value.length < 50) content.push(param.name + ": " + value + "<br/>");
            else content.push(param.name + ": " + "<span style=\"text-overflow: ellipsis;max-width:500px\">" + value + "</span><br/>");
          }
        }
        catch (e) {}
      });

      content.push("Фреймворк: " + dojo.version.toString() + "<br/>");
      content.push("Приложение: " + parus.parus8.version.toString() + "<br/>");


      if (parus.parus8._embeddedMode && parus.embeddedMode.version) {

        content.push("Модули интеграции:<br/>");

        for (var key in parus.embeddedMode.version) {
          content.push(
          String.fromCharCode(160) + String.fromCharCode(160) + "модуль " + key + ": " + parus.embeddedMode.version[key].version.toString() + (
          parus.embeddedMode.version[key].revision ? " (" + parus.embeddedMode.version[key].revision.toString() + ")" : "") + "<br/>");

        }
      }


      content.push("</div>");
      content.push("</div>");

      content.push("<div style=\"margin-bottom:5px\">");
      content.push("Пользователь системы:");
      content.push("<div style=\"margin-left:5px;font-weight:normal;white-space: nowrap;\">");
      content.push("Идентификатор: " + response.documentElement.getAttribute("userid") + "<br/>");
      content.push("Полное имя: " + response.documentElement.getAttribute("username") + "<br/>");
      content.push("Внешний идентификатор: " + response.documentElement.getAttribute("userexternalname") + "<br/>");
      content.push("Провайдер аутентификации: " + response.documentElement.getAttribute("userexternalprovider") + "<br/>");
      content.push("Способ аутентификации: " + parus.parus8.formatAuthType(response.documentElement.getAttribute("userauthtype")) + "<br/>");
      content.push("Организация: " + response.documentElement.getAttribute("companyname") + "<br/>");
      content.push("Полное наименование организации: " + response.documentElement.getAttribute("companyfullname"));
      content.push("</div>");
      content.push("</div>");

      //      content.push("<div style=\"margin-bottom:5px\">");
      //      content.push("Также вы можете воспользоваться <a href=\"../.system/diag.html#hidelicense\" target=\"_blank\">страницей диагностики</a>.");
      //      content.push("</div>");
      content.push("</div>");

      parus.parus8.notificationMessage(content.join(""), onDone);
    });

  },

  applicationNode: function() {

    var application = parus.applicationContent || null;
    if (!application) {

      if (parus.parus8._embeddedMode) {
        var content = dojo.cache("parus", "embeddedApplication.html");

        var node = dojo.place(content, dojo.body(), "last");

        dojo.parser.parse({
          rootNode: dojo.body(),
          template: true
        });

        parus.applicationContent = {
          domNode: dojo.place("<div></div>", parus.WindowContainer.domNode, "last")
        };

        parus.embeddedMode.registerOnShowCallback(function() {
          parus.WindowContainer.resize();
        });
      }
      else {


        var content = dojo.cache("parus", "application.html");
        var title = "Парус" + String.fromCharCode(174) + String.fromCharCode(160) + "Сведение" + String.fromCharCode(160) + "отчетности";

        if (parus.parus8.optionValue("BalanceOnlineShowLicenseTitle") != "0") {

          var response = parus.database.execute("applicationInfo");

          if (response) {

            title = String.fromCharCode(174) + parus.parus8.nodeField(parus.parus8.rowNodes(response)[0], "HOLDER").split(" ").join(String.fromCharCode(160)) + String.fromCharCode(160) + "-" + String.fromCharCode(160) + parus.parus8.nodeField(parus.parus8.rowNodes(response)[0], "TITLE").split(" ").join(String.fromCharCode(160));

          }

        };
        document.title = title;
        content = content.split("${title}").join(title);

        new dijit.layout.ContentPane({
          parseOnLoad: false,
          content: content,
          "class": parus.parus8.zoomContainerClass(),
          style: "overflow:hidden",
          region: "center"
        }, dojo.place("<div id=\"bodyContainer\" dojoType=\"dijit.layout.BorderContainer\" gutters=\"false\" style=\"width:100%;height:100%;border:0 none\"></div>", dojo.body(), "last").appendChild(document.createElement("div")));


        var themesList = "";
        for (var i = 0; i < parus.parus8._themes.length; i++) {
          if (themesList) themesList = themesList + ",";
          themesList = themesList + "'" + parus.parus8._themes[i].getAttribute("id") + "'";
        };

        var text = [];

        dojo.forEach(parus.parus8._intfs, function(intf) {

          if (parus.parus8._themeEditorMode) {
            text.push("<li dojoType=\"dijit.MenuItem\" iconClass=\"noIcon\"");
            text.push(" onClick=\"parus.parus8.changeInterfaceSchema([], 'custom', '" + intf.id + "')\">");
            text.push(" <div overclass=\"custom\" schema=\"" + intf.id + "\">");
            text.push("(В разработке)" + " - " + intf.title);
            text.push("</div></li>");
          }
          else for (var i = 0; i < parus.parus8._themes.length; i++) {
            text.push("<li dojoType=\"dijit.MenuItem\" iconClass=\"noIcon\"");
            text.push(" onClick=\"parus.parus8.changeInterfaceSchema([" + themesList + "], '" + parus.parus8._themes[i].getAttribute("id") + "', '" + intf.id + "')\">");
            text.push(" <div overclass=\"" + parus.parus8._themes[i].getAttribute("id") + "\" schema=\"" + intf.id + "\">");
            text.push(parus.parus8._themes[i].getAttribute("title") + " - " + intf.title);
            text.push("</div></li>");
          }
        });

        dojo.query("*[jsid='schemaSelectMenu']", dojo.byId("bodyContainer"))[0].innerHTML = text.join("");

        dojo.parser.parse({
          rootNode: dojo.byId("bodyContainer")
        });

        var versionContent = "";


        if (parus.database.attributes["major"] || parus.database.attributes["minor"] || parus.database.attributes["release"] || parus.database.attributes["build"] || versionInfoPanel) {
          versionContent += "(Версия " + parus.database.attributes["major"] + "." + parus.database.attributes["minor"] + "." + parus.database.attributes["release"] + "." + parus.database.attributes["build"] + ")";
          versionContent = "<a style=\"font-size:80%\" class=\"balanceApplicationVersionInfo\" href=\"javascript:parus.parus8.aboutBox()\" >" + versionContent + "</a>";
        }


        if (parus.database.attributes["user"]) versionContent += "&#160;&#160;&#160;<span class=\"balanceApplicationVersionInfo\">Пользователь:&#160;<b>" + parus.database.attributes["user"] + "</b></span>";

        if (parus.database.attributes["company"]) versionContent += "&#160;&#160;&#160;<span class=\"balanceApplicationVersionInfo\">Организация:&#160;<b>" + parus.database.attributes["company"] + "</b></span>";


        versionInfoPanel.setContent(versionContent);

        dojo.connect(window, "onresize", this, function() {
          dijit.byNode(parus.WindowContainer.domNode.parentNode).resize();
        });

        if (dojo.isEdge) {
          zoomSelectPanel.domNode.style.display = "none";
          zoomLabelPanel.domNode.style.display = "none";
        }

        if (dojo.isIE) {
          zoomSelectPanel.domNode.style.display = "none";
          zoomLabelPanel.domNode.style.display = "none";
        }
      }

    };


    return dojo.place("<div></div>", parus.applicationContent.domNode, "only");

  },

  changeInterfaceSchema: function(range, selected, startupObject) {

    var currentSchema = parus.WindowContainer.domNode.getAttribute("schema");

    startupObject = startupObject || currentSchema;

    dojo.forEach(zoomSelect.dropDown.getChildren(), function(item) {
      var itemNode = dojo.query("[overclass]", item.containerNode)[0];
      if (itemNode.getAttribute("overclass") == selected) {
        var content = dojo.place(itemNode.outerHTML, zoomSelect.containerNode, "only");
        content.setAttribute("overclass", "");
        content.style.fontWeight = "bold";
      }
    });

    dojo.forEach(schemaSelect.dropDown.getChildren(), function(item) {
      var itemNode = dojo.query("[overclass]", item.containerNode)[0];
      if ((itemNode.getAttribute("overclass") == selected) && (itemNode.getAttribute("schema") == startupObject)) {
        var content = dojo.place(itemNode.outerHTML, schemaSelect.containerNode, "only");
        content.style.fontWeight = "bold";
      }
    });


    var classes = document.body.className.split(" ");

    dojo.forEach(range, function(option) {
      var idx = dojo.indexOf(classes, option);
      if (idx >= 0) {
        classes[idx] = selected;
      }
    });

    if ((classes.join(" ") == document.body.className) && (currentSchema == startupObject)) return;

    loadingDiv.style.display = "";

    dojo.fadeOut({
      node: parus.WindowContainer.domNode,
      duration: 300,
      onEnd: function() {

        document.body.className = classes.join(" ");
        dojo.cookie("bc", document.body.className, {
          expires: 365
        });
        dojo.cookie("bs", startupObject, {
          expires: 365
        });


        if (currentSchema == startupObject) dijit.byNode(parus.WindowContainer.domNode.parentNode).resize();
        else {
          parus.balance.TabContainer = null;
          parus[startupObject].startup();
        };

        dojo.fadeIn({
          node: parus.WindowContainer.domNode,
          duration: 700,
          onBegin: function() {
            loadingDiv.style.display = "none";
          }

        }).play();

      }
    }).play();
  },

  interfaceSchemaLoaded: function(schema) {

    parus.WindowContainer.domNode.setAttribute("schema", schema);

    parus.WindowContainer.layout();


    var classes = document.body.className.split(" ");

    dojo.forEach(zoomSelect.dropDown.getChildren(), function(item) {
      var itemNode = dojo.query("[overclass]", item.containerNode)[0];
      if (dojo.indexOf(classes, itemNode.getAttribute("overclass")) >= 0) {
        var content = dojo.place(itemNode.outerHTML, zoomSelect.containerNode, "only");
        content.setAttribute("overclass", "");
        content.style.fontWeight = "bold";
      }
    });

    dojo.forEach(schemaSelect.dropDown.getChildren(), function(item) {
      var itemNode = dojo.query("[overclass]", item.containerNode)[0];
      if ((dojo.indexOf(classes, itemNode.getAttribute("overclass")) >= 0) && (itemNode.getAttribute("schema") == schema)) {
        var content = dojo.place(itemNode.outerHTML, schemaSelect.containerNode, "only");
        content.style.fontWeight = "bold";
      }
    });


  },

  showApplication: function(onShown) {

    loadingDiv.style.display = "none";

    var widget = dijit.byNode(parus.WindowContainer.domNode.parentNode) || parus.WindowContainer;

    widget.resize();

    parus.WindowContainer.layout();
    dojo.fadeIn({
      node: parus.WindowContainer.domNode,
      onEnd: function() {
        if (onShown) onShown();
      }
    }).play();

  },


  _closedNotifications: null,

  _shownNotifications: null,

  _notificationTimeout: null,
  _notificationCheckDisabled: null,

  closeNotification: function(rn) {
    this._closedNotifications = this._closedNotifications || [];
    this._closedNotifications.push(rn);
    this.checkNotifications();
  },

  checkNotifications: function() {

    if (this._notificationTimeout) {
      clearTimeout(this._notificationTimeout);
      this._notificationTimeout = null;
    }

    if (!parus.notificationsContainer) {
      this._notificationTimeout = setTimeout(dojo.hitch(this, this.checkNotifications), 1000);
      return;
    };

    this._closedNotifications = this._closedNotifications || [];
    var shownNotifications = "";



    parus.database.query("BalanceNotifications", {}, dojo.hitch(this, function(response) {

      if (this._notificationCheckDisabled) return;

      var notifications = parus.parus8.rowNodes(response);

      var html = [];

      dojo.forEach(notifications, dojo.hitch(this, function(node) {

        if (dojo.indexOf(this._closedNotifications, parus.parus8.nodeField(node, "RN")) != -1) return;

        shownNotifications = shownNotifications + ";" + parus.parus8.nodeField(node, "RN");

        html.push("<div jsid=\"notification" + parus.parus8.nodeField(node, "RN") + "\" class=\"balanceNotification\" >");

        html.push("<table width=\"100%\">");
        html.push("<tr>");

        html.push("<td>");
        html.push("<div class=\"balanceNotificationContent\">");


        html.push(parus.parus8.nodeField(node, "NOTIFICATION").replace(/\n/g, "<br/>"));

        html.push("</div>");

        html.push("</td>");

        html.push("<td width=\"30\" valign=\"top\">");

        html.push("<button class=\"titleButton\"");
        html.push("dojoType=\"dijit.form.Button\"");
        html.push("iconClass=\"balanceApplicationCloseNotificationButton\"");
        html.push("label=\"Скрыть\"");
        html.push("onClick=\"parus.parus8.closeNotification('" + parus.parus8.nodeField(node, "RN") + "')\"");
        html.push("showLabel=\"false\"");
        html.push("style=\"margin-left:0px;margin-right:0px;position:absolute;right:2px\">");
        html.push("</button>");

        html.push("</td>");

        html.push("</tr>");
        html.push("</table>");


        html.push("</div>");


      }));


      var changed = (shownNotifications != this._shownNotifications);
      this._shownNotifications = shownNotifications;

      if (html.length) {
        dojo.place(html.join(" "), parus.notificationsContainer.containerNode, "only");

        dojo.parser.parse({
          rootNode: parus.notificationsContainer.containerNode,
          template: true
        });

        if (parus.notificationsContainer.domNode.style.display != "") {
          parus.notificationsContainer.domNode.style.display = "";
          parus.WindowContainer.layout();
        }
        else if (changed) {
          parus.WindowContainer.layout();
        }

      }
      else if (!parus.notificationsContainer.domNode.style.display) {
        parus.notificationsContainer.domNode.style.display = "none";
        parus.WindowContainer.layout();
      }
      else if (changed) {
        parus.WindowContainer.layout();
      }

      this._notificationTimeout = setTimeout(dojo.hitch(this, this.checkNotifications), 60000);

    }), dojo.hitch(this, function(e) {
      //do nothing - do not enqueue new checks
      if (e.status === 403) {
        //parus.database.connected = null;
        console.log("Session is unauthorized - disable check notifications", e);
        this._notificationCheckDisabled = true;
      }
    }), true);

  },


  hexEncodeParams: function(params) {

    var codes = [];

    dojo.forEach(params, function(str) {

      if (str) {
        var strstr = str.toString();
        for (var i = 0; i < strstr.length; i++) {
          s = strstr.charCodeAt(i).toString(16);
          while (s.length < 4)
          s = "0" + s;
          codes.push(s);
        }
      }
      codes.push("00ff");
    });

    return codes.join("");
  },

  hexDecodeParams: function(params) {

    result = [];

    if (params) {

      var bytes = [];
      for (var i = 0; i < params.length; i += 4) {
        bytes.push(+("0x" + params.substr(i, 4)));
      }

      var s = "";

      dojo.forEach(bytes, function(b) {
        if (b == 255) {
          result.push(s);
          s = "";
        }
        else s = s + String.fromCharCode(b);
      });
    }

    return result;
  },

  enqueuedUserReport: function(queue) {

    var timeout = 10 * 1000;

    var waitTime = parus.parus8.optionValue("ReportsPrintQueueUserReportsWaitTime") || 60; //seconds
    var start = (new Date()).getTime();

    var progressIndicator = new parus.progressDialog({
      message: "Ожидание пользовательского отчета..."
    });
    progressIndicator.show();

    setTimeout(function() {

      var response = parus.database.execute("enqueuedUserReportStatus", {
        NQUEUE: queue
      });

      if (response) {

        var status = parus.parus8.nodeField(parus.parus8.rowNodes(response)[0], "NSTATUS");

        if (status == "3") {
          progressIndicator.close();
          progressIndicator.destroyRecursive();

          parus.parus8.errorMessage("Пользовательский отчет выполнен с ошибкой.<br/>" + (parus.parus8.nodeField(parus.parus8.rowNodes(response)[0], "SERRTEXT") || ""));
          return;
        }

        else if (status == "2") {
          progressIndicator.close();
          progressIndicator.destroyRecursive();

          var form = document.createElement("form");
          form.method = "GET";
          form.action = parus.database.getEnqueuedReportUrl();

          var input = document.createElement("input");
          input.type = "hidden";
          input.name = "queue";
          input.value = queue;
          form.appendChild(input);

          document.body.appendChild(form);
          form.submit();
          document.body.removeChild(form);


          /*window.open(parus.database.getEnqueuedReportUrl(queue), "_blank"); */
          /*
           parus.parus8.notificationMessage(
           "Пользовательский отчет выполнен успешно. <br/>" +
           "Вы можете скачать отчет по этой <a href=\"" + parus.database.getEnqueuedReportUrl(queue) + "\">ссылке</a>."); */
          return;
        }
        else if (status == null) {
          progressIndicator.close();
          progressIndicator.destroyRecursive();

          parus.parus8.errorMessage("Пользовательский отчет удален из очереди.");
          return;

        }
      };

      if (((new Date()).getTime() - start) / 1000 > waitTime) {
        progressIndicator.close();
        progressIndicator.destroyRecursive();

        parus.parus8.errorMessage("Время ожидания готовности отчета истекло. Для просмотра отчета перейдите в раздел \"Очередь печати отчетов\"");
        return;
      }
      else setTimeout(arguments.callee, timeout);

    }, timeout);
  },

  toLetters: function(num) {
    var r = "";
    do {
      var i = (num - 1) % 26;
      r = String.fromCharCode(65 + i) + r;
      num = Math.floor((num - i) / 26);
    } while (num > 0);
    return r;
  },

  maxGridRecords: null

});

dojo.mixin(dojo, {
  isRegExp: function(obj) {
    return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
  }
});

dojo.extend(dijit.MenuItem, {

  actionCode: "",

  itemAction: false,

  detailAction: false,

  "default": false,

  userProcRN: null,

  userReportRN: null,

  userAppRN: null,

  userObjectsGrid: null,

  customIcon: "",

  toolBarButton: null,

  defaultIcon: "",

  hiddenBySettings: false,

  inAbonent: false,

  removeForApplications: "",

  features: ""

});


dojo.extend(dijit.form.Button, {

  itemsPerAction: 0

});

dojo.extend(dijit.Menu, {

  actionsButtonPane: null,

  inAbonentUserApps: null,

  inAbonentUserProcs: null,

  inAbonentUserReports: null,

  preAction: null

});

dojo.extend(dojox.grid.EnhancedGrid, {

  abonentFields: "",

  abonentFieldsNeeded: false,

  gridid: "",

  autoSelected: false

});



dojo.extend(dijit.form.CheckBox, {

  numericValue: -1

});

if (window.hasOwnProperty) if (window.hasOwnProperty("scrollX")) {
  var _oldGetBox = dojo.window.getBox;
  dojo.mixin(dojo.window, {
    getBox: function() {
      var oldBox = _oldGetBox();
      oldBox.w -= window.scrollX;
      oldBox.h -= window.scrollY;
      return oldBox;
    }
  });
};


var _oldPlaceAt = dijit.place.at;

dojo.mixin(dijit.place, {

  at: function(node, pos, corners, padding, layoutNode) {
    var h = node.style.height;
    node.style.height = "auto";
    var rh = node.offsetHeight;
    var vph = dijit.Viewport.getEffectiveBox(node.ownerDocument).h;
    node.style.height = h;

    var r = _oldPlaceAt(node, pos, corners, padding, layoutNode);

    if (r.h < rh) if (r.y > 0) {

      var dy = rh - r.h;
      if (dy > r.y) dy = r.y;

      r.y = r.y - dy;
      r.h = r.h + dy;

    }
    else {
      var dy = rh - r.h;
      if (dy > vph - (r.y + r.h)) dy = vph - (r.y + r.h);

      r.h = r.h + dy;
    }

    r.y = r.y / parus.parus8.getZoom();
    r.x = r.x / parus.parus8.getZoom();

    dojo.style(node, {
      top: r.y + "px",
      left: r.x + "px",
      height: r.h + "px",
      overflowY: "auto",
      overflowX: "hidden"
    });

    return r;
  }
});

dojo.extend(dojox.grid.cells.Cell, {
  intPart: null,
  fracPart: null
});

dojox.grid.DataGrid.markupFactory = function(props, node, ctor, cellFunc) {
  return dojox.grid._Grid.markupFactory(props, node, ctor, dojo.partial(dojox.grid.DataGrid.cell_markupFactory, function(node, cell) {
    if (node && cell) dojo.mixin(cell, {
      sortField: node.getAttribute("sortField"),
      dataType: node.getAttribute("dataType"),
      aggregate: node.getAttribute("aggregate"),
      intPart: node.getAttribute("intPart"),
      fracPart: node.getAttribute("fracPart")
    });
    if (cellFunc) cellFunc(node, cell);
  }));
};


dojox.grid.EnhancedGrid.markupFactory = function(props, node, ctor, cellFunc) {
  return dojox.grid._Grid.markupFactory(props, node, ctor, dojo.partial(dojox.grid.DataGrid.cell_markupFactory, function(node, cell) {
    if (node && cell) dojo.mixin(cell, {
      sortField: node.getAttribute("sortField"),
      dataType: node.getAttribute("dataType"),
      aggregate: node.getAttribute("aggregate"),
      intPart: node.getAttribute("intPart"),
      fracPart: node.getAttribute("fracPart")
    });
    if (cellFunc) cellFunc(node, cell);
  }));
};

dojo.extend(dojox.grid.DataGrid, {

  colorConditions: null,

  getSortProps: function() {
    var c = this.getCell(this.getSortIndex());
    if (!c) {
      if (this.sortFields) {
        return this.sortFields;
      }
      return null;
    } else {
      var desc = c["sortDesc"];
      var si = !(this.sortInfo > 0);
      if (typeof desc == "undefined") {
        desc = si;
      } else {
        desc = si ? !desc : desc;
      }
      return [{
        field: c.field,
        attribute: c.sortField || c.field,
        descending: !! desc
      }];
    }
  },

  _clearData: function() {
    this.selection.clear();
    this.updateRowCount(0);
    this._by_idty = {};
    this._by_idx = [];
    this._pages = [];
    this._bop = this._eop = -1;
    this._isLoaded = false;
    this._isLoading = false;
  }
});


dojo.extend(dojox.grid.enhanced._FocusManager, {
  _setActiveColHeader: dojox.grid._FocusManager.prototype._setActiveColHeader
});

var _defKeyDown = dojox.grid.enhanced._Events.prototype.onKeyDown;
var _defMouseOver = dojox.grid._Events.prototype.onMouseOver;

dojo.extend(dojox.grid.enhanced._Events, {

  _focusNeeded: function() {
    if (dijit.popup._stack.length != 0) return false;
    var focus = dijit.getFocus();
    var result = true;
    if (focus && focus.node) {
      var w = dijit.getEnclosingWidget(focus.node);
      if (w && (w.declaredClass == "dojox.grid.enhanced.columnsFilterCombobox")) result = false;
      else result = (focus.node.nodeName != "INPUT");
      if (result) if (dojo.dom.isDescendant(focus.node, this.domNode)) result = false;
    }
    return result;
  },

  onKeyDown: function(e) {
    if (e.altKey || e.metaKey) return;

    if (!this._focusNeeded()) return;

    this.focus.findAndFocusGridCell();
    var dk = dojo.keys;
    switch (e.keyCode) {
    case dk.HOME:
      this.focus.setFocusIndex(this.focus.rowIndex, 0);
      dojo.stopEvent(e);
      break;
    case dk.END:
      this.focus.setFocusIndex(this.focus.rowIndex, this.layout.cellCount - 1);
      dojo.stopEvent(e);
      break;
    case dk.SPACE:
      if (this.focus.cell.declaredClass != "dojox.grid.cells.MultipleRowSelector") {
        if (!this.selection.isSelected(this.focus.rowIndex) || (this.selection.getSelectedCount() > 1)) this.selection.toggleSelect(this.focus.rowIndex);
        dojo.stopEvent(e);
      };
      break;
    default:
      _defKeyDown.apply(this, arguments);
      break;
    };
  },

  onMouseOver: function(e) {
    _defMouseOver.apply(this, arguments);
    if (!dojo.isChrome && !dojo.isMozilla) if (this._focusNeeded()) this.focus.focusGrid();
  }

});

var _defformat = dojox.grid.cells._Base.prototype._defaultFormat;

dojo.extend(dojox.grid.cells._Base, {

  _defaultFormat: function(inValue, callArgs) {
    var customStyle = "";
    var value = _defformat.apply(this, arguments) || "";


    if (this.field && this.grid.colorConditions && this.grid.colorConditions.length) {

      var v = (value == this.defaultValue) ? "" : value.toString();

      var matched = "";
      var notmatched = "";

      var checkCondition = function(condition, v) {

        if (condition.mask.match(/.*!.*/)) notmatched = condition.color;

        if (condition.mask) dojo.forEach(condition.mask.split(";"), function(mask) {

          if (mask.substring(0, 1) == "!") {
            var matcher = ((mask == "!*") ? /^.+$/m : dojo.data.util.filter.patternToRegExp(mask.substring(1, mask.length), false));
            if (v.match(matcher)) notmatched = "";
          }
          else {
            var matcher = ((mask == "*") ? /^.+$/m : dojo.data.util.filter.patternToRegExp(mask, false));
            if (v.match(matcher)) matched = condition.color;
          }
        })
        else {
          var vn = dojo.number.parse(v),
              fn = dojo.number.parse(condition.fromValue),
              tn = dojo.number.parse(condition.toValue);
          if (!isNaN(vn)) {
            if (!isNaN(fn) && !isNaN(tn) && (vn >= fn) && (vn <= tn)) matched = condition.color;
            else if (!isNaN(fn) && isNaN(tn) && (vn >= fn)) matched = condition.color;
            else if (isNaN(fn) && !isNaN(tn) && (vn <= tn)) matched = condition.color;
          };

          var pattern = {
            selector: "date",
            datePattern: "dd.MM.yyyy"
          };

          var vd = dojo.date.locale.parse(v, pattern),
              fd = dojo.date.locale.parse(condition.fromValue, pattern),
              td = dojo.date.locale.parse(condition.toValue, pattern);

          if (vd) {
            if (fd && td && (vd >= fd) && (vd <= td)) matched = condition.color;
            else if (fd && !td && (vd >= fd)) matched = condition.color;
            else if (!fd && td && (vd <= td)) matched = condition.color;
          };

        }

      };

      dojo.forEach(this.grid.colorConditions, dojo.hitch(this, function(condition) {

        if (matched || notmatched) return;

        if (condition.field == this.field) checkCondition(condition, v || "");
      }));


      dojo.forEach(this.grid.colorConditions, dojo.hitch(this, function(condition) {

        if (matched || notmatched) return;

        if (condition.applyToRow && (condition.field != this.field)) {

          var item = this.grid._by_idx[callArgs[1]];
          if (item) {
            var conditionValue = this.grid.store.getValue(item.item, condition.field);
            dojo.forEach(this.grid.layout.cells, function(cell) {
              if (cell && (cell.field == condition.field)) conditionValue = _defformat.apply(cell, [conditionValue, [conditionValue, callArgs[1], cell]]);
            });
            checkCondition(condition, conditionValue || "");
          }
        }

      }));

      if (matched && !notmatched) customStyle = "background-color:" + parus.parus8.colorToCssColor(matched);
      else if (notmatched && !matched) customStyle = "background-color:" + parus.parus8.colorToCssColor(notmatched);
    }

    if (customStyle) this.customStyles.push(customStyle);

    return value;
  }

});

dojo.extend(dojox.grid.Selection, {
  onChanged: function() {
    for (var inIndex in this.selected) {
      var rowNode = this.grid.getRowNode(inIndex);
      if (rowNode) this.grid.styleRowNode(inIndex, rowNode);
    }
  }
});


dojo.extend(dojox.grid.DataSelection, {

  getSelectedIndex: function() {
    var r = dojox.grid.Selection.prototype.getFirstSelected.call(this);
    if ((r < 0) && (this.grid.rowCount > 0)) {
      this.selectRange(0, 0);
      r = 0;
    }
    return r;
  },

  getSelected: function() {
    var result = [];
    var item = this.getFirstSelected();
    for (var i = 0; i < this.getSelectedCount(); i++) {
      result.push(item);
      item = this.getNextSelected(item);
    };
    return result;
  },

  getNextSelected: function(inPrev) {
    var old_idx = this.grid.getItemIndex(inPrev);
    var idx = dojox.grid.Selection.prototype.getNextSelected.call(this, old_idx);
    if (idx == -1) {
      return null;
    }
    var item = this.grid.getItem(idx);
    if (!item) {
      this.grid.store.sync = true;
      this.grid._fetch(idx, false);
      item = this.grid.getItem(idx);
    }
    return this.grid.getItem(idx);
  }

});


var _defNativeSelect = dojox.grid.cells.MultipleRowSelector.prototype._nativeSelect;

dojo.extend(dojox.grid.cells.MultipleRowSelector, {

  _nativeSelect: function(index, value) {
    if (this.grid.autoSelected && index) this.grid.selection.deselect(0);
    this.grid.autoSelected = false;
    return _defNativeSelect.apply(this, arguments);
  }

});


dojo.extend(dojox.grid.cells._Widget, {
  getValue: function(inRowIndex) {
    if (this.widget.validate) if (this.widget.validate()) return this.widget.get("value");
    else return this.grid.store.getValue(this.grid.getItem(inRowIndex), this.field);
    else return this.widget.get("value");
  }
});

dojo.declare("parus.gridInplaceEditor", [dijit.Editor], {
  _sCall: function(name, args) {
    if (!dojo.isFF || this.editNode.ownerDocument.defaultView) return dojo.withGlobal(this.window, name, dijit._editor.selection, args);
  }
});

dojo.extend(dojox.grid.cells.Editor, {

  formatNode: function(inNode, inDatum, inRowIndex) {
    this.content = inDatum;
    this.inherited("formatNode", arguments);
  },

  createWidget: function(inNode, inDatum, inRowIndex) {
    var widget = new this.widgetClass(this.getWidgetProps(inDatum), inNode);
    dojo.connect(widget, "onLoad", dojo.hitch(this, "populateEditor"));
    widget.set("value", this.content);
    return widget;
  }
});

dojo.extend(dijit._editor.plugins._FontDropDown, {

  templateString: "<span style='white-space: nowrap' class='dijit dijitReset dijitInline'>" + "<label class='dijitLeft dijitInline' for='${selectId}'>${label}</label>" + "<input style='width: 100px' dojoType='dijit.form.FilteringSelect' required='false' labelType='html' labelAttr='label' searchAttr='name' " + "tabIndex='-1' id='${selectId}' dojoAttachPoint='select' value=''/>" + "</span>"

});


if (dojo.isIE == 9) {

  var getFilterValue = function(node, format) {
    try {
      return node.filters.item("DXImageTransform.Microsoft.Alpha");
    } catch (e) {
      return format ? {} : null;
    }
  };

  dojo.mixin(dojo, {

    _getOpacity: function(node) {
      try {
        return getFilterValue(node).Opacity / 100;
      } catch (e) {
        return 1;
      }
    },

    _setOpacity: function(node, opacity) {

      var ov = opacity * 100,
          opaque = opacity == 1;
      node.style.zoom = opaque ? "" : 1;

      if (!getFilterValue(node)) {
        if (opaque) {
          return opacity;
        }
        node.style.filter += " progid:DXImageTransform.Microsoft.Alpha(Opacity=" + ov + ")";
      } else {
        getFilterValue(node, 1).Opacity = ov;
      }

      getFilterValue(node, 1).Enabled = !opaque;

      if (node.nodeName.toLowerCase() == "tr") {
        d.query("> td", node).forEach(function(i) {
          d._setOpacity(i, opacity);
        });
      }
      return opacity;


    }


  });

};

if (dojo.isIE >= 10) {

  dojo._getIeDispatcher = function() {
    return new Function("return " + dojo._scopeName + "._ieDispatcher(arguments, this)");
  };

  dojo._ieDispatcher = function(args, sender) {
    var ap = Array.prototype,
        h = dojo._ie_listener.handlers,
        c = args.callee,
        ls = c[dojo._ieListenersName],
        t = h[c.target];
    var r = t && t.apply(sender, args);
    var lls = [].concat(ls);
    for (var i in lls) {
      var f = h[lls[i]];
      if (!(i in ap) && f) {
        r = f.apply(sender, args);
      }
    }
    return r;
  };

  var _oldTextBoxPostCreate = dijit.form.TextBox.prototype.postCreate;

  dojo.extend(dijit.form.TextBox, {
    postCreate: function() {
      var _this = this;
      _oldTextBoxPostCreate.apply(_this, arguments);
      this.connect(this.textbox, "oninput", "_onInput");
    }
  });

  dojo.extend(dijit.form._DateTimeTextBox, {
    intermediateChanges: true
  });


  var _oldBindDomNode = dijit.Menu.prototype.bindDomNode;

  dojo.extend(dijit.Menu, {

    bindDomNode: function() {
      var _this = this;
      var result = _oldBindDomNode.apply(_this, arguments);


      dojo.forEach(this._bindings, function(binding) {
        if (!binding) return;
        if (!binding.connects) return;

        dojo.forEach(binding.connects, function(connect) {
          if (!connect) return;
          if (!connect.length) return;
          if (connect[1] == "oncontextmenu") {
            dojo.connect(connect[0], connect[1], _this, function(evt) {
              _this._scheduleOpen(evt.target, connect[0], {
                x: evt.pageX,
                y: evt.pageY
              });
              return false;
            });
          }
        });

      });

      return result;
    }

  });


  var _oldOverLeftResizeArea = dojox.grid._HeaderBuilder.prototype.overLeftResizeArea;
  var _oldOverRightResizeArea = dojox.grid._HeaderBuilder.prototype.overRightResizeArea;

  dojox.grid._HeaderBuilder = dojo.extend(dojox.grid._HeaderBuilder, {

    overLeftResizeArea: function(e) {
      var result = _oldOverLeftResizeArea.apply(this, arguments);
      if (result && dojo.hasClass(e.target, "dijitCheckBox")) result = false;
      return result;
    },

    overRightResizeArea: function(e) {
      var result = _oldOverRightResizeArea.apply(this, arguments);
      if (result && dojo.hasClass(e.target, "dijitCheckBox")) result = false;
      return result;
    }
  });


}

if (dojo.isMozilla) {

  var _oldCreateView = dojox.grid.EnhancedGrid.prototype.createView;

  dojo.extend(dojox.grid.EnhancedGrid, {

    createView: function() {

      var view = _oldCreateView.apply(this, arguments);
      var getCellX = view.header.getCellX;
      view.header.getCellX = function(e) {
        var r = getCellX.apply(this, arguments);

        var ascendDom = function(inNode, inWhile) {
          for (var n = inNode; n && inWhile(n); n = n.parentNode) {}
          return n;
        };

        var makeNotTagName = function(inTagName) {
          var name = inTagName.toUpperCase();
          return function(node) {
            return node.tagName != name;
          };
        };

        var n = ascendDom(e.target, makeNotTagName("th"));
        if (n && n !== e.target && dojo.dom.isDescendant(e.target, n)) {
          r -= n.firstChild.offsetLeft;
        }

        return r;
      }
      view.scrollboxNode.style.overflow = "scroll";
      return view;
    }

  });
}


if (dojo.isIE) {
  dojo.getComputedStyle = function(node) {
    return node ? (node.nodeType == 1 ? node.currentStyle : {}) : {};
  }
}

if (dojo.isFF >= 13) {

  var _oldDoScroll = dojox.grid._View.prototype.doscroll;

  dojo.extend(dojox.grid._View, {

    _nativeScroll: false,

    doscroll: function(inEvent) {
      this._nativeScroll = true;
      _oldDoScroll.apply(this, arguments);
      this._nativeScroll = false;
    },

    setScrollTop: function(inTop) {
      this.lastTop = inTop;
      if (!this._nativeScroll) this.scrollboxNode.scrollTop = inTop;
      return this.scrollboxNode.scrollTop;
    }

  });

};

dojo.extend(dijit.Tree, {

  listMode: false,

  hiddenMode: false,

  allowChecks: false,

  checked: null,

  _unselected: null,

  _createTreeNode: function(args) {
    return new parus.checkTreeNode(args);
  },

  dndController: "parus.dndSelector",

  uncheckAll: function() {
    while (this.checked.length > 0)
    this.checked[0].setChecked(false);
    this.selectedNode.setChecked(true);
    this.onClick();
  },

  setCheckedPaths: function(paths) {
    var tree = this;

    var selectPath = function(path, nodes, def) {
      var nextPath = path.shift();
      var nextNode = dojo.filter(nodes, function(node) {
        return node.getIdentity() == nextPath;
      })[0];
      if ( !! nextNode) {
        if (path.length) {
          tree._expandNode(nextNode).then(function() {
            selectPath(path, nextNode.getChildren(), def);
          });
        } else {
          def.callback(nextNode);
        }
      } else def.errback({
        log: false
      });

    }

    var setNodes = function(newNodes) {
      dojo.forEach(newNodes, function(newNode) {
        if (newNode[0]) newNode[1].setChecked(true);
      });
    }


    return new dojo.DeferredList(dojo.map(paths, function(path) {
      var d = new dojo.Deferred();

      if (path.length) {
        if (tree._loadDeferred) tree._loadDeferred.then(function() {
          selectPath(path, [tree.rootNode], d);
        });
      } else {
        d.errback({
          log: false
        });
      }
      return d;
    })).addCallback(setNodes);


  },

  _initState: function() {
    this.checked = [];
    if (this.persist) {
      var cookie = dojo.cookie(this.cookieName);
      this._openedItemIds = {};
      if (cookie) {
        dojo.forEach(cookie.split(','), function(item) {
          this._openedItemIds[item] = true;
        }, this);
      }
    }
  },

  forAllChildren: function(root, func) {
    var tree = this;

    var forAllNodes = function(parentTreeNode) {
      if (func) func(parentTreeNode);
      tree._expandNode(parentTreeNode).then(function() {
        dojo.forEach(parentTreeNode.getChildren(), forAllNodes);
      });
    };

    forAllNodes(root);

  }


});

dojo.declare("parus.dndSelector", [dijit.tree._dndSelector], {

  onClickPress: function(e) {
    if (e.type == "pointerdown" && !dojo.mouse.isLeft(e)) {
      e.stopPropagation();
      e.preventDefault();
      return false;
    }
    else if ((this.tree.allowChecks && !this.listMode && this.current) && (dojo.isDescendant(e.target, this.current.checkNode))) {
      this.current.setChecked(!this.current.getChecked());
      e.stopPropagation();
      e.preventDefault();
      return false;
    }
    else return this.inherited(arguments);
  },

  setSelection: function(newSelection) {

    if (newSelection.length && this.tree.selectedNode && (newSelection[0].getChecked && !newSelection[0].getChecked()) && this.tree.checked.length) while (this.tree.checked.length > 0) this.tree.checked[0].setChecked(false);

    this.inherited(arguments);

    if (newSelection && this.tree.allowChecks) dojo.forEach(newSelection, function(node) {
      node.setChecked(true);
    });

  }

});

dojo.declare("parus.checkTreeNode", dijit._TreeNode, {

  getParent: function() {
    return this.domNode ? this.inherited(arguments) : null
  },

  getChecked: function() {
    return (dojo.indexOf(this.tree.checked, this) != -1);
  },

  setChecked: function(checked) {
    var idx = dojo.indexOf(this.tree.checked, this);
    if (!this.checkNode) return;

    if (checked) {
      if (idx == -1) {
        this.tree.checked.push(this);
        dojo.addClass(this.checkNode, "dijitCheckBoxChecked");
      }
    }
    else {
      if (idx != -1) {
        this.tree.checked.splice(idx, 1);
        dojo.removeClass(this.checkNode, "dijitCheckBoxChecked");
      }
    }
  },


  checkNode: null,

  buildRendering: function() {
    this.inherited(arguments);
    if (this.tree.allowChecks && !this.tree.listMode) {
      var checkNodeText = "<img style=\"margin-left:3px\" src=\"" + (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")).toString() + "\" class=\"dijitCheckBox dijitCheckBoxIcon\">";
      if (dojo.isIE) {
        dojo.place(checkNodeText, this.labelNode, "before");
        this.checkNode = this.labelNode.previousSibling;
      }
      else this.checkNode = dojo.place(checkNodeText + "</img>", this.labelNode, "before");
    }
  },

  setSelected: function(selected) {
    this.inherited(arguments);
    if (selected) {
      var t = this.tree.rootNode.domNode.parentNode.offsetTop;
      var h = this.tree.domNode.clientHeight;
      var c = this.rowNode.offsetTop;
      var s = this.tree.domNode.scrollTop;
      if ((t + h < c - s) || (t > c)) this.rowNode.scrollIntoView(false);
    }
  }

});


//chrome bug
var _oldOnAddChild = dijit.layout.ScrollingTabController.prototype.onAddChild;
dojo.extend(dijit.layout.ScrollingTabController, {

  onAddChild: function(page, insertIndex) {
    var w = dojo.style(this.containerNode, "width");
    _oldOnAddChild.apply(this, arguments);
    dojo.style(this.containerNode, "width", ((w || 50000) + 200) + "px");
  }
});


var _hasDropDownExtension = {

  _onDropDownMouseUp: function(e) {
    if (e && this._docHandler) this.disconnect(this._docHandler);
    if (this._opened && this.dropDown.focus && this.dropDown.autoFocus !== false) setTimeout(dojo.hitch(this.dropDown, "focus"), 1);
  }
};

if (dojo.isIE) dojo.extend(dijit.form.DropDownButton, {
  _fillContent: function() {
    var source = this.srcNodeRef;
    var dest = this.containerNode;
    if (source && dest) {
      while (source.hasChildNodes()) {
        var child = source.firstChild;
        if (dojo.hasAttr(child, "data-dojo-type") || dojo.hasAttr(child, "dojoType") || dojo.hasAttr(child, "data-" + dojo._scopeName + "-type") || dojo.hasAttr(child, dojo._scopeName + "Type")) {
          this.dropDownContainer = this.ownerDocument.createElement("div");
          this.dropDownContainer.appendChild(child);
        } else {
          dest.appendChild(child);
        }
      }
    }
  }
});


dojo.extend(dijit._HasDropDown, _hasDropDownExtension);
dojo.extend(dijit.form.DropDownButton, _hasDropDownExtension);
dojo.extend(dijit.form.ComboBoxMixin, _hasDropDownExtension);
dojo.extend(dijit.form.ComboBox, _hasDropDownExtension);
dojo.extend(dijit.form.FilteringSelect, _hasDropDownExtension);
dojo.extend(dijit.form.Select, _hasDropDownExtension);
dojo.extend(dijit.form._DateTimeTextBox, _hasDropDownExtension);
dojo.extend(dijit.layout._ScrollingTabControllerMenuButton, _hasDropDownExtension);


var oldTabContainerLayout = dijit.layout.TabContainer.prototype.layout;
dojo.extend(dijit.layout.TabContainer, {

  _lastLayoutChildren: null,

  layout: function() {
    var result = oldTabContainerLayout.apply(this, arguments);
    if (this.tablist.layoutAlign == "left") {
      var layoutChildren = this.getChildren().length;
      if ((layoutChildren != this._lastLayoutChildren) || !this.tablist.domNode.style.width) this.tablist.domNode.style.width = (dojo.position(this.tablistSpacer).x - 1) + "px";
      this._lastLayoutChildren = layoutChildren;
    }
    return result;
  }

});

dojo.isEdge = (navigator.userAgent.indexOf("Edge") >= 0);

dojo.isTrident = (navigator.userAgent.indexOf("Trident") >= 0);

dojo.isYandex = (navigator.userAgent.indexOf("YaBrowser") >= 0);

dojo.isChromiumEdge = (navigator.userAgent.indexOf("Edg/") >= 0);
dojo.isChromiumOpera = (navigator.userAgent.indexOf("OPR/") >= 0);


dojo.connect(window, "onresize", function() {
  dojo.forEach(dijit.Dialog._dialogStack, function(stackItem) {
    if (stackItem.dialog) stackItem.dialog._position();
  });
});

if (dojo.isIE <= 8) dojo.connect(dijit.layout.StackContainer.prototype, "selectChild", function(page) {
  var nodes = dojo.query(">*", page.containerNode);
  nodes.orphan();
  if (this.resize) this.resize();
  nodes.forEach(function(node) {
    page.containerNode.appendChild(node);
  });
  if (this.resize) this.resize();
});

dojo.extend(dijit.form._DateTimeTextBox, {
  autoWidth: false
});

//setInterval(function(){console.log("focus", dijit.getFocus())}, 1000);